[2.0] Started to implement proxy object handling. Introduced a configuration switch for partial objects (allowPartialObjects) that defaults to TRUE. Setting to FALSE enables proxying and lazy-loading.
This commit is contained in:
parent
e0488ff8fc
commit
ecd30bc242
@ -100,7 +100,7 @@ class ClassLoader
|
|||||||
$class .= $this->_basePaths[$prefix] . DIRECTORY_SEPARATOR;
|
$class .= $this->_basePaths[$prefix] . DIRECTORY_SEPARATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
$class .= str_replace(array($this->_namespaceSeparator, '_'), DIRECTORY_SEPARATOR, $className)
|
$class .= str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $className)
|
||||||
. $this->_fileExtension;
|
. $this->_fileExtension;
|
||||||
|
|
||||||
if ($this->_checkFileExists) {
|
if ($this->_checkFileExists) {
|
||||||
|
@ -7,7 +7,7 @@ namespace Doctrine\DBAL\Types;
|
|||||||
*
|
*
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
class VarcharType extends Type
|
class StringType extends Type
|
||||||
{
|
{
|
||||||
/** @override */
|
/** @override */
|
||||||
public function getSqlDeclaration(array $fieldDeclaration, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
|
public function getSqlDeclaration(array $fieldDeclaration, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
|
||||||
@ -24,6 +24,6 @@ class VarcharType extends Type
|
|||||||
/** @override */
|
/** @override */
|
||||||
public function getName()
|
public function getName()
|
||||||
{
|
{
|
||||||
return 'Varchar';
|
return 'string';
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ abstract class Type
|
|||||||
'int' => 'Doctrine\DBAL\Types\IntegerType',
|
'int' => 'Doctrine\DBAL\Types\IntegerType',
|
||||||
'smallint' => 'Doctrine\DBAL\Types\SmallIntType',
|
'smallint' => 'Doctrine\DBAL\Types\SmallIntType',
|
||||||
'bigint' => 'Doctrine\DBAL\Types\BigIntType',
|
'bigint' => 'Doctrine\DBAL\Types\BigIntType',
|
||||||
'varchar' => 'Doctrine\DBAL\Types\VarcharType',
|
'string' => 'Doctrine\DBAL\Types\StringType',
|
||||||
'text' => 'Doctrine\DBAL\Types\TextType',
|
'text' => 'Doctrine\DBAL\Types\TextType',
|
||||||
'datetime' => 'Doctrine\DBAL\Types\DateTimeType',
|
'datetime' => 'Doctrine\DBAL\Types\DateTimeType',
|
||||||
'decimal' => 'Doctrine\DBAL\Types\DecimalType',
|
'decimal' => 'Doctrine\DBAL\Types\DecimalType',
|
||||||
|
@ -46,15 +46,52 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
|||||||
'metadataCacheImpl' => null,
|
'metadataCacheImpl' => null,
|
||||||
'metadataDriverImpl' => new AnnotationDriver(),
|
'metadataDriverImpl' => new AnnotationDriver(),
|
||||||
'dqlClassAliasMap' => array(),
|
'dqlClassAliasMap' => array(),
|
||||||
'cacheDir' => null
|
'cacheDir' => null,
|
||||||
|
'allowPartialObjects' => true
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a boolean flag that specifies whether partial objects are allowed.
|
||||||
|
*
|
||||||
|
* If partial objects are allowed, Doctrine will never use proxies or lazy loading
|
||||||
|
* and you always only get what you explicitly query for.
|
||||||
|
*
|
||||||
|
* @return boolean Whether partial objects are allowed.
|
||||||
|
*/
|
||||||
|
public function getAllowPartialObjects()
|
||||||
|
{
|
||||||
|
return $this->_attributes['allowPartialObjects'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a boolean flag that specifies whether partial objects are allowed.
|
||||||
|
*
|
||||||
|
* If partial objects are allowed, Doctrine will never use proxies or lazy loading
|
||||||
|
* and you always only get what you explicitly query for.
|
||||||
|
*
|
||||||
|
* @param boolean $allowed Whether partial objects are allowed.
|
||||||
|
*/
|
||||||
|
public function setAllowPartialObjects($allowed)
|
||||||
|
{
|
||||||
|
$this->_attributes['allowPartialObjects'] = $allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the directory where Doctrine writes any necessary cache files.
|
||||||
|
*
|
||||||
|
* @param string $dir
|
||||||
|
*/
|
||||||
public function setCacheDir($dir)
|
public function setCacheDir($dir)
|
||||||
{
|
{
|
||||||
$this->_attributes['cacheDir'] = $dir;
|
$this->_attributes['cacheDir'] = $dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the directory where Doctrine writes any necessary cache files.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getCacheDir()
|
public function getCacheDir()
|
||||||
{
|
{
|
||||||
return $this->_attributes['cacheDir'];
|
return $this->_attributes['cacheDir'];
|
||||||
@ -70,41 +107,81 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
|||||||
$this->_attributes['dqlClassAliasMap'] = $map;
|
$this->_attributes['dqlClassAliasMap'] = $map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cache driver implementation that is used for metadata caching.
|
||||||
|
*
|
||||||
|
* @param object $driverImpl
|
||||||
|
*/
|
||||||
public function setMetadataDriverImpl($driverImpl)
|
public function setMetadataDriverImpl($driverImpl)
|
||||||
{
|
{
|
||||||
$this->_attributes['metadataDriverImpl'] = $driverImpl;
|
$this->_attributes['metadataDriverImpl'] = $driverImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cache driver implementation that is used for the mapping metadata.
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
public function getMetadataDriverImpl()
|
public function getMetadataDriverImpl()
|
||||||
{
|
{
|
||||||
return $this->_attributes['metadataDriverImpl'];
|
return $this->_attributes['metadataDriverImpl'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cache driver implementation that is used for query result caching.
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
public function getResultCacheImpl()
|
public function getResultCacheImpl()
|
||||||
{
|
{
|
||||||
return $this->_attributes['resultCacheImpl'];
|
return $this->_attributes['resultCacheImpl'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cache driver implementation that is used for query result caching.
|
||||||
|
*
|
||||||
|
* @param object $cacheImpl
|
||||||
|
*/
|
||||||
public function setResultCacheImpl($cacheImpl)
|
public function setResultCacheImpl($cacheImpl)
|
||||||
{
|
{
|
||||||
$this->_attributes['resultCacheImpl'] = $cacheImpl;
|
$this->_attributes['resultCacheImpl'] = $cacheImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cache driver implementation that is used for the query cache (SQL cache).
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
public function getQueryCacheImpl()
|
public function getQueryCacheImpl()
|
||||||
{
|
{
|
||||||
return $this->_attributes['queryCacheImpl'];
|
return $this->_attributes['queryCacheImpl'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cache driver implementation that is used for the query cache (SQL cache).
|
||||||
|
*
|
||||||
|
* @param object $cacheImpl
|
||||||
|
*/
|
||||||
public function setQueryCacheImpl($cacheImpl)
|
public function setQueryCacheImpl($cacheImpl)
|
||||||
{
|
{
|
||||||
$this->_attributes['queryCacheImpl'] = $cacheImpl;
|
$this->_attributes['queryCacheImpl'] = $cacheImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cache driver implementation that is used for metadata caching.
|
||||||
|
*
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
public function getMetadataCacheImpl()
|
public function getMetadataCacheImpl()
|
||||||
{
|
{
|
||||||
return $this->_attributes['metadataCacheImpl'];
|
return $this->_attributes['metadataCacheImpl'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cache driver implementation that is used for metadata caching.
|
||||||
|
*
|
||||||
|
* @param object $cacheImpl
|
||||||
|
*/
|
||||||
public function setMetadataCacheImpl($cacheImpl)
|
public function setMetadataCacheImpl($cacheImpl)
|
||||||
{
|
{
|
||||||
$this->_attributes['metadataCacheImpl'] = $cacheImpl;
|
$this->_attributes['metadataCacheImpl'] = $cacheImpl;
|
||||||
|
@ -26,9 +26,11 @@ namespace Doctrine\ORM;
|
|||||||
* For that purpose he generates proxy class files on the fly as needed.
|
* For that purpose he generates proxy class files on the fly as needed.
|
||||||
*
|
*
|
||||||
* @author Roman Borschel <roman@code-factory.org>
|
* @author Roman Borschel <roman@code-factory.org>
|
||||||
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
class DynamicProxyGenerator
|
class DynamicProxyGenerator
|
||||||
{
|
{
|
||||||
|
private static $_ns = 'Doctrine\Generated\Proxies\\';
|
||||||
private $_cacheDir = '/Users/robo/dev/php/tmp/gen/';
|
private $_cacheDir = '/Users/robo/dev/php/tmp/gen/';
|
||||||
private $_em;
|
private $_em;
|
||||||
|
|
||||||
@ -36,78 +38,66 @@ class DynamicProxyGenerator
|
|||||||
{
|
{
|
||||||
$this->_em = $em;
|
$this->_em = $em;
|
||||||
if ($cacheDir === null) {
|
if ($cacheDir === null) {
|
||||||
$cacheDir = sys_get_tmp_dir();
|
$cacheDir = sys_get_temp_dir();
|
||||||
}
|
}
|
||||||
$this->_cacheDir = $cacheDir;
|
$this->_cacheDir = $cacheDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Gets a reference proxy instance.
|
||||||
*
|
*
|
||||||
* @param <type> $className
|
* @param string $className
|
||||||
* @param <type> $identifier
|
* @param mixed $identifier
|
||||||
* @return <type>
|
* @return object
|
||||||
*/
|
*/
|
||||||
public function getProxy($className, $identifier)
|
public function getReferenceProxy($className, $identifier)
|
||||||
{
|
{
|
||||||
$proxyClassName = str_replace('\\', '_', $className) . 'Proxy';
|
$class = $this->_em->getClassMetadata($className);
|
||||||
|
$proxyClassName = str_replace('\\', '_', $className) . 'RProxy';
|
||||||
if ( ! class_exists($proxyClassName, false)) {
|
if ( ! class_exists($proxyClassName, false)) {
|
||||||
|
$this->_em->getMetadataFactory()->setMetadataFor(self::$_ns . $proxyClassName, $class);
|
||||||
$fileName = $this->_cacheDir . $proxyClassName . '.g.php';
|
$fileName = $this->_cacheDir . $proxyClassName . '.g.php';
|
||||||
if ( ! file_exists($fileName)) {
|
if ( ! file_exists($fileName)) {
|
||||||
$this->_generateProxyClass($className, $identifier, $proxyClassName, $fileName);
|
$this->_generateReferenceProxyClass($className, $identifier, $proxyClassName, $fileName);
|
||||||
}
|
}
|
||||||
require $fileName;
|
require $fileName;
|
||||||
}
|
}
|
||||||
$proxyClassName = '\Doctrine\Generated\Proxies\\' . $proxyClassName;
|
$proxyClassName = '\\' . self::$_ns . $proxyClassName;
|
||||||
return new $proxyClassName($this->_em, $this->_em->getClassMetadata($className), $identifier);
|
return new $proxyClassName($this->_em, $class, $identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an association proxy instance.
|
||||||
|
*/
|
||||||
|
public function getAssociationProxy($owner, \Doctrine\ORM\Mapping\AssociationMapping $assoc)
|
||||||
|
{
|
||||||
|
$proxyClassName = str_replace('\\', '_', $assoc->getTargetEntityName()) . 'AProxy';
|
||||||
|
if ( ! class_exists($proxyClassName, false)) {
|
||||||
|
//die("$proxyClassName!");
|
||||||
|
$this->_em->getMetadataFactory()->setMetadataFor(self::$_ns . $proxyClassName, $this->_em->getClassMetadata($assoc->getTargetEntityName()));
|
||||||
|
$fileName = $this->_cacheDir . $proxyClassName . '.g.php';
|
||||||
|
if ( ! file_exists($fileName)) {
|
||||||
|
$this->_generateAssociationProxyClass($assoc->getTargetEntityName(), $proxyClassName, $fileName);
|
||||||
|
}
|
||||||
|
require $fileName;
|
||||||
|
}
|
||||||
|
$proxyClassName = '\\' . self::$_ns . $proxyClassName;
|
||||||
|
return new $proxyClassName($this->_em, $assoc, $owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a proxy class.
|
* Generates a proxy class.
|
||||||
*
|
*
|
||||||
* @param <type> $className
|
* @param string $className
|
||||||
* @param <type> $id
|
* @param mixed $id
|
||||||
* @param <type> $proxyClassName
|
* @param string $proxyClassName
|
||||||
* @param <type> $fileName
|
* @param string $fileName
|
||||||
*/
|
*/
|
||||||
private function _generateProxyClass($className, $id, $proxyClassName, $fileName)
|
private function _generateReferenceProxyClass($className, $id, $proxyClassName, $fileName)
|
||||||
{
|
{
|
||||||
$class = $this->_em->getClassMetadata($className);
|
$class = $this->_em->getClassMetadata($className);
|
||||||
$file = self::$_proxyClassTemplate;
|
$file = self::$_proxyClassTemplate;
|
||||||
|
|
||||||
if (is_array($id) && count($id) > 1) {
|
|
||||||
// it's a composite key. keys = field names, values = values.
|
|
||||||
$values = array_values($id);
|
|
||||||
$keys = array_keys($id);
|
|
||||||
} else {
|
|
||||||
$values = is_array($id) ? array_values($id) : array($id);
|
|
||||||
$keys = $class->getIdentifierFieldNames();
|
|
||||||
}
|
|
||||||
$paramIndex = 1;
|
|
||||||
$identifierCondition = 'prx.' . $keys[0] . ' = ?' . $paramIndex++;
|
|
||||||
for ($i=1, $c=count($keys); $i < $c; ++$i) {
|
|
||||||
$identifierCondition .= ' AND prx.' . $keys[$i] . ' = ?' . $paramIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
$parameters = 'array(';
|
|
||||||
$first = true;
|
|
||||||
foreach ($values as $value) {
|
|
||||||
if ($first) {
|
|
||||||
$first = false;
|
|
||||||
} else {
|
|
||||||
$parameters = ', ';
|
|
||||||
}
|
|
||||||
$parameters .= "'" . $value . "'";
|
|
||||||
}
|
|
||||||
$parameters .= ')';
|
|
||||||
|
|
||||||
$hydrationSetters = '';
|
|
||||||
foreach ($class->getReflectionProperties() as $name => $prop) {
|
|
||||||
if ( ! $class->hasAssociation($name)) {
|
|
||||||
$hydrationSetters .= '$this->_class->setValue($this, \'' . $name . '\', $scalar[0][\'prx_' . $name . '\']);' . PHP_EOL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$methods = '';
|
$methods = '';
|
||||||
foreach ($class->getReflectionClass()->getMethods() as $method) {
|
foreach ($class->getReflectionClass()->getMethods() as $method) {
|
||||||
if ($method->isPublic() && ! $method->isFinal()) {
|
if ($method->isPublic() && ! $method->isFinal()) {
|
||||||
@ -147,12 +137,11 @@ class DynamicProxyGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
$placeholders = array(
|
$placeholders = array(
|
||||||
'<proxyClassName>', '<className>', '<identifierCondition>',
|
'<proxyClassName>', '<className>',
|
||||||
'<parameters>', '<hydrationSetters>', '<methods>', '<sleepImpl>'
|
'<methods>', '<sleepImpl>'
|
||||||
);
|
);
|
||||||
$replacements = array(
|
$replacements = array(
|
||||||
$proxyClassName, $className, $identifierCondition, $parameters,
|
$proxyClassName, $className, $methods, $sleepImpl
|
||||||
$hydrationSetters, $methods, $sleepImpl
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$file = str_replace($placeholders, $replacements, $file);
|
$file = str_replace($placeholders, $replacements, $file);
|
||||||
@ -160,6 +149,70 @@ class DynamicProxyGenerator
|
|||||||
file_put_contents($fileName, $file);
|
file_put_contents($fileName, $file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a proxy class.
|
||||||
|
*
|
||||||
|
* @param string $className
|
||||||
|
* @param mixed $id
|
||||||
|
* @param string $proxyClassName
|
||||||
|
* @param string $fileName
|
||||||
|
*/
|
||||||
|
private function _generateAssociationProxyClass($className, $proxyClassName, $fileName)
|
||||||
|
{
|
||||||
|
$class = $this->_em->getClassMetadata($className);
|
||||||
|
$file = self::$_assocProxyClassTemplate;
|
||||||
|
|
||||||
|
$methods = '';
|
||||||
|
foreach ($class->getReflectionClass()->getMethods() as $method) {
|
||||||
|
if ($method->isPublic() && ! $method->isFinal()) {
|
||||||
|
$methods .= PHP_EOL . 'public function ' . $method->getName() . '(';
|
||||||
|
$firstParam = true;
|
||||||
|
$parameterString = '';
|
||||||
|
foreach ($method->getParameters() as $param) {
|
||||||
|
if ($firstParam) {
|
||||||
|
$firstParam = false;
|
||||||
|
} else {
|
||||||
|
$parameterString .= ', ';
|
||||||
|
}
|
||||||
|
$parameterString .= '$' . $param->getName();
|
||||||
|
}
|
||||||
|
$methods .= $parameterString . ') {' . PHP_EOL;
|
||||||
|
$methods .= '$this->_load();' . PHP_EOL;
|
||||||
|
$methods .= 'return parent::' . $method->getName() . '(' . $parameterString . ');';
|
||||||
|
$methods .= '}' . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sleepImpl = '';
|
||||||
|
if ($class->getReflectionClass()->hasMethod('__sleep')) {
|
||||||
|
$sleepImpl .= 'return parent::__sleep();';
|
||||||
|
} else {
|
||||||
|
$sleepImpl .= 'return array(';
|
||||||
|
$first = true;
|
||||||
|
foreach ($class->getReflectionProperties() as $name => $prop) {
|
||||||
|
if ($first) {
|
||||||
|
$first = false;
|
||||||
|
} else {
|
||||||
|
$sleepImpl .= ', ';
|
||||||
|
}
|
||||||
|
$sleepImpl .= "'" . $name . "'";
|
||||||
|
}
|
||||||
|
$sleepImpl .= ');';
|
||||||
|
}
|
||||||
|
|
||||||
|
$placeholders = array(
|
||||||
|
'<proxyClassName>', '<className>',
|
||||||
|
'<methods>', '<sleepImpl>'
|
||||||
|
);
|
||||||
|
$replacements = array(
|
||||||
|
$proxyClassName, $className, $methods, $sleepImpl
|
||||||
|
);
|
||||||
|
|
||||||
|
$file = str_replace($placeholders, $replacements, $file);
|
||||||
|
|
||||||
|
file_put_contents($fileName, $file);
|
||||||
|
}
|
||||||
|
|
||||||
/** Proxy class code template */
|
/** Proxy class code template */
|
||||||
private static $_proxyClassTemplate =
|
private static $_proxyClassTemplate =
|
||||||
'<?php
|
'<?php
|
||||||
@ -176,8 +229,7 @@ namespace Doctrine\Generated\Proxies {
|
|||||||
}
|
}
|
||||||
private function _load() {
|
private function _load() {
|
||||||
if ( ! $this->_loaded) {
|
if ( ! $this->_loaded) {
|
||||||
$scalar = $this->_em->createQuery(\'select prx from <className> prx where <identifierCondition>\')->execute(<parameters>, \Doctrine\ORM\Query::HYDRATE_SCALAR);
|
$this->_em->getUnitOfWork()->getEntityPersister($this->_class->getClassName())->load($this->_identifier, $this);
|
||||||
<hydrationSetters>
|
|
||||||
unset($this->_em);
|
unset($this->_em);
|
||||||
unset($this->_class);
|
unset($this->_class);
|
||||||
$this->_loaded = true;
|
$this->_loaded = true;
|
||||||
@ -194,4 +246,39 @@ namespace Doctrine\Generated\Proxies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
|
|
||||||
|
private static $_assocProxyClassTemplate =
|
||||||
|
'<?php
|
||||||
|
/** This class was generated by the Doctrine ORM. DO NOT EDIT THIS FILE. */
|
||||||
|
namespace Doctrine\Generated\Proxies {
|
||||||
|
class <proxyClassName> extends \<className> {
|
||||||
|
private $_em;
|
||||||
|
private $_assoc;
|
||||||
|
private $_owner;
|
||||||
|
private $_loaded = false;
|
||||||
|
public function __construct($em, $assoc, $owner) {
|
||||||
|
$this->_em = $em;
|
||||||
|
$this->_assoc = $assoc;
|
||||||
|
$this->_owner = $owner;
|
||||||
|
}
|
||||||
|
private function _load() {
|
||||||
|
if ( ! $this->_loaded) {
|
||||||
|
$this->_assoc->load($this->_owner, $this, $this->_em);
|
||||||
|
unset($this->_em);
|
||||||
|
unset($this->_owner);
|
||||||
|
unset($this->_assoc);
|
||||||
|
$this->_loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<methods>
|
||||||
|
|
||||||
|
public function __sleep() {
|
||||||
|
if (!$this->_loaded) {
|
||||||
|
throw new RuntimeException("Not fully loaded proxy can not be serialized.");
|
||||||
|
}
|
||||||
|
<sleepImpl>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}';
|
||||||
}
|
}
|
||||||
|
@ -146,6 +146,7 @@ class EntityManager
|
|||||||
$this->_conn->getDatabasePlatform());
|
$this->_conn->getDatabasePlatform());
|
||||||
$this->_metadataFactory->setCacheDriver($this->_config->getMetadataCacheImpl());
|
$this->_metadataFactory->setCacheDriver($this->_config->getMetadataCacheImpl());
|
||||||
$this->_unitOfWork = new UnitOfWork($this);
|
$this->_unitOfWork = new UnitOfWork($this);
|
||||||
|
$this->_proxyGenerator = new DynamicProxyGenerator($this, '/Users/robo/dev/php/tmp/gen/');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -401,9 +402,6 @@ class EntityManager
|
|||||||
public function refresh($entity)
|
public function refresh($entity)
|
||||||
{
|
{
|
||||||
throw DoctrineException::notImplemented();
|
throw DoctrineException::notImplemented();
|
||||||
/*$this->_mergeData($entity, $this->getRepository(get_class($entity))->find(
|
|
||||||
$entity->identifier(), Query::HYDRATE_ARRAY),
|
|
||||||
true);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -445,7 +443,7 @@ class EntityManager
|
|||||||
* Gets the repository for an entity class.
|
* Gets the repository for an entity class.
|
||||||
*
|
*
|
||||||
* @param string $entityName The name of the Entity.
|
* @param string $entityName The name of the Entity.
|
||||||
* @return Doctrine\ORM\EntityRepository The repository.
|
* @return EntityRepository The repository.
|
||||||
*/
|
*/
|
||||||
public function getRepository($entityName)
|
public function getRepository($entityName)
|
||||||
{
|
{
|
||||||
@ -458,7 +456,7 @@ class EntityManager
|
|||||||
if ($customRepositoryClassName !== null) {
|
if ($customRepositoryClassName !== null) {
|
||||||
$repository = new $customRepositoryClassName($entityName, $metadata);
|
$repository = new $customRepositoryClassName($entityName, $metadata);
|
||||||
} else {
|
} else {
|
||||||
$repository = new \Doctrine\ORM\EntityRepository($this, $metadata);
|
$repository = new EntityRepository($this, $metadata);
|
||||||
}
|
}
|
||||||
$this->_repositories[$entityName] = $repository;
|
$this->_repositories[$entityName] = $repository;
|
||||||
|
|
||||||
@ -547,23 +545,17 @@ class EntityManager
|
|||||||
default:
|
default:
|
||||||
throw DoctrineException::updateMe("No hydrator found for hydration mode '$hydrationMode'.");
|
throw DoctrineException::updateMe("No hydrator found for hydration mode '$hydrationMode'.");
|
||||||
}
|
}
|
||||||
}/* else if ($this->_hydrators[$hydrationMode] instanceof Closure) {
|
}
|
||||||
$this->_hydrators[$hydrationMode] = $this->_hydrators[$hydrationMode]($this);
|
|
||||||
}*/
|
|
||||||
return $this->_hydrators[$hydrationMode];
|
return $this->_hydrators[$hydrationMode];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a hydrator for a hydration mode.
|
*
|
||||||
*
|
|
||||||
* @param mixed $hydrationMode
|
|
||||||
* @param object $hydrator Either a hydrator instance or a Closure that creates a
|
|
||||||
* hydrator instance.
|
|
||||||
*/
|
*/
|
||||||
/*public function setHydrator($hydrationMode, $hydrator)
|
public function getProxyGenerator()
|
||||||
{
|
{
|
||||||
$this->_hydrators[$hydrationMode] = $hydrator;
|
return $this->_proxyGenerator;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method to create EntityManager instances.
|
* Factory method to create EntityManager instances.
|
||||||
|
@ -63,8 +63,6 @@ class EntityRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the repository, causing all managed entities to become detached.
|
* Clears the repository, causing all managed entities to become detached.
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
public function clear()
|
public function clear()
|
||||||
{
|
{
|
||||||
@ -80,35 +78,17 @@ class EntityRepository
|
|||||||
*/
|
*/
|
||||||
public function find($id, $hydrationMode = null)
|
public function find($id, $hydrationMode = null)
|
||||||
{
|
{
|
||||||
if (is_array($id) && count($id) > 1) {
|
|
||||||
// it's a composite key. keys = field names, values = values.
|
|
||||||
$values = array_values($id);
|
|
||||||
$keys = array_keys($id);
|
|
||||||
} else {
|
|
||||||
$values = is_array($id) ? array_values($id) : array($id);
|
|
||||||
$keys = $this->_classMetadata->getIdentifier();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check identity map first
|
// Check identity map first
|
||||||
if ($entity = $this->_em->getUnitOfWork()->tryGetById($id, $this->_classMetadata->getRootClassName())) {
|
if ($entity = $this->_em->getUnitOfWork()->tryGetById($id, $this->_classMetadata->getRootClassName())) {
|
||||||
return $entity; // Hit!
|
return $entity; // Hit!
|
||||||
}
|
}
|
||||||
|
|
||||||
$dql = 'select e from ' . $this->_classMetadata->getClassName() . ' e where ';
|
if ( ! is_array($id) || count($id) <= 1) {
|
||||||
$conditionDql = '';
|
$value = is_array($id) ? array_values($id) : array($id);
|
||||||
$paramIndex = 1;
|
$id = array_combine($this->_classMetadata->getIdentifier(), $value);
|
||||||
foreach ($keys as $key) {
|
|
||||||
if ($conditionDql != '') $conditionDql .= ' and ';
|
|
||||||
$conditionDql .= 'e.' . $key . ' = ?' . $paramIndex++;
|
|
||||||
}
|
|
||||||
$dql .= $conditionDql;
|
|
||||||
|
|
||||||
$q = $this->_em->createQuery($dql);
|
|
||||||
foreach ($values as $index => $value) {
|
|
||||||
$q->setParameter($index, $value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $q->getSingleResult($hydrationMode);
|
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,43 +130,6 @@ class EntityRepository
|
|||||||
return $hydrationMode === Doctrine::HYDRATE_ARRAY ? array_shift($results) : $results->getFirst();
|
return $hydrationMode === Doctrine::HYDRATE_ARRAY ? array_shift($results) : $results->getFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* findBySql
|
|
||||||
* finds records with given SQL where clause
|
|
||||||
* returns a collection of records
|
|
||||||
*
|
|
||||||
* @param string $dql DQL after WHERE clause
|
|
||||||
* @param array $params query parameters
|
|
||||||
* @param int $hydrationMode Query::HYDRATE_ARRAY or Query::HYDRATE_RECORD
|
|
||||||
* @return Doctrine_Collection
|
|
||||||
*
|
|
||||||
* @todo This actually takes DQL, not SQL, but it requires column names
|
|
||||||
* instead of field names. This should be fixed to use raw SQL instead.
|
|
||||||
*/
|
|
||||||
public function findBySql($dql, array $params = array(), $hydrationMode = null)
|
|
||||||
{
|
|
||||||
return $this->_createQuery()->where($dql)->execute($params, $hydrationMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* findByDql
|
|
||||||
* finds records with given DQL where clause
|
|
||||||
* returns a collection of records
|
|
||||||
*
|
|
||||||
* @param string $dql DQL after WHERE clause
|
|
||||||
* @param array $params query parameters
|
|
||||||
* @param int $hydrationMode Query::HYDRATE_ARRAY or Query::HYDRATE_RECORD
|
|
||||||
* @return Doctrine_Collection
|
|
||||||
*/
|
|
||||||
public function findByDql($dql, array $params = array(), $hydrationMode = null)
|
|
||||||
{
|
|
||||||
$query = new Query($this->_em);
|
|
||||||
$component = $this->getComponentName();
|
|
||||||
$dql = 'FROM ' . $component . ' WHERE ' . $dql;
|
|
||||||
|
|
||||||
return $query->query($dql, $params, $hydrationMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds support for magic finders.
|
* Adds support for magic finders.
|
||||||
* findByColumnName, findByRelationAlias
|
* findByColumnName, findByRelationAlias
|
||||||
@ -211,7 +154,7 @@ class EntityRepository
|
|||||||
|
|
||||||
if (isset($by)) {
|
if (isset($by)) {
|
||||||
if ( ! isset($arguments[0])) {
|
if ( ! isset($arguments[0])) {
|
||||||
throw \Doctrine\Common\DoctrineException::updateMe('You must specify the value to findBy.');
|
throw DoctrineException::updateMe('You must specify the value to findBy.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$fieldName = Doctrine::tableize($by);
|
$fieldName = Doctrine::tableize($by);
|
||||||
@ -222,11 +165,11 @@ class EntityRepository
|
|||||||
} else if ($this->_classMetadata->hasRelation($by)) {
|
} else if ($this->_classMetadata->hasRelation($by)) {
|
||||||
$relation = $this->_classMetadata->getRelation($by);
|
$relation = $this->_classMetadata->getRelation($by);
|
||||||
if ($relation['type'] === Doctrine_Relation::MANY) {
|
if ($relation['type'] === Doctrine_Relation::MANY) {
|
||||||
throw \Doctrine\Common\DoctrineException::updateMe('Cannot findBy many relationship.');
|
throw DoctrineException::updateMe('Cannot findBy many relationship.');
|
||||||
}
|
}
|
||||||
return $this->$method($relation['local'], $arguments[0], $hydrationMode);
|
return $this->$method($relation['local'], $arguments[0], $hydrationMode);
|
||||||
} else {
|
} else {
|
||||||
throw \Doctrine\Common\DoctrineException::updateMe('Cannot find by: ' . $by . '. Invalid field or relationship alias.');
|
throw DoctrineException::updateMe('Cannot find by: ' . $by . '. Invalid field or relationship alias.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
namespace Doctrine\ORM\Internal\Hydration;
|
namespace Doctrine\ORM\Internal\Hydration;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Types\Type;
|
||||||
use Doctrine\Common\DoctrineException;
|
use Doctrine\Common\DoctrineException;
|
||||||
use \PDO;
|
use \PDO;
|
||||||
|
|
||||||
@ -184,7 +185,7 @@ abstract class AbstractHydrator
|
|||||||
$classMetadata = $this->_lookupDeclaringClass($classMetadata, $fieldName);
|
$classMetadata = $this->_lookupDeclaringClass($classMetadata, $fieldName);
|
||||||
$cache[$key]['fieldName'] = $fieldName;
|
$cache[$key]['fieldName'] = $fieldName;
|
||||||
$cache[$key]['isScalar'] = false;
|
$cache[$key]['isScalar'] = false;
|
||||||
$cache[$key]['type'] = $classMetadata->getTypeOfField($fieldName);
|
$cache[$key]['type'] = Type::getType($classMetadata->getTypeOfField($fieldName));
|
||||||
$cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName);
|
$cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName);
|
||||||
$cache[$key]['dqlAlias'] = $this->_resultSetMapping->getEntityAlias($key);
|
$cache[$key]['dqlAlias'] = $this->_resultSetMapping->getEntityAlias($key);
|
||||||
} else {
|
} else {
|
||||||
@ -196,17 +197,15 @@ abstract class AbstractHydrator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$fieldName = $cache[$key]['fieldName'];
|
|
||||||
|
|
||||||
if ($cache[$key]['isScalar']) {
|
if ($cache[$key]['isScalar']) {
|
||||||
$rowData['scalars'][$fieldName] = $value;
|
$rowData['scalars'][$cache[$key]['fieldName']] = $value;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$dqlAlias = $cache[$key]['dqlAlias'];
|
$dqlAlias = $cache[$key]['dqlAlias'];
|
||||||
|
|
||||||
if (isset($cache[$key]['isDiscriminator'])) {
|
if (isset($cache[$key]['isDiscriminator'])) {
|
||||||
$rowData[$dqlAlias][$fieldName] = $value;
|
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $value;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +213,7 @@ abstract class AbstractHydrator
|
|||||||
$id[$dqlAlias] .= '|' . $value;
|
$id[$dqlAlias] .= '|' . $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rowData[$dqlAlias][$fieldName] = $cache[$key]['type']->convertToPHPValue($value);
|
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $cache[$key]['type']->convertToPHPValue($value);
|
||||||
|
|
||||||
if ( ! isset($nonemptyComponents[$dqlAlias]) && $value !== null) {
|
if ( ! isset($nonemptyComponents[$dqlAlias]) && $value !== null) {
|
||||||
$nonemptyComponents[$dqlAlias] = true;
|
$nonemptyComponents[$dqlAlias] = true;
|
||||||
@ -259,7 +258,7 @@ abstract class AbstractHydrator
|
|||||||
//$fieldName = $classMetadata->getFieldNameForLowerColumnName($columnName);
|
//$fieldName = $classMetadata->getFieldNameForLowerColumnName($columnName);
|
||||||
$cache[$key]['fieldName'] = $fieldName;
|
$cache[$key]['fieldName'] = $fieldName;
|
||||||
$cache[$key]['isScalar'] = false;
|
$cache[$key]['isScalar'] = false;
|
||||||
$cache[$key]['type'] = $classMetadata->getTypeOfField($fieldName);
|
$cache[$key]['type'] = Type::getType($classMetadata->getTypeOfField($fieldName));
|
||||||
$cache[$key]['dqlAlias'] = $this->_resultSetMapping->getEntityAlias($key);
|
$cache[$key]['dqlAlias'] = $this->_resultSetMapping->getEntityAlias($key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,12 @@ use Doctrine\Common\Collections\Collection;
|
|||||||
/**
|
/**
|
||||||
* The ObjectHydrator constructs an object graph out of an SQL result set.
|
* The ObjectHydrator constructs an object graph out of an SQL result set.
|
||||||
*
|
*
|
||||||
* @author robo
|
* @author Roman Borschel <roman@code-factory.org>
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
class ObjectHydrator extends AbstractHydrator
|
class ObjectHydrator extends AbstractHydrator
|
||||||
{
|
{
|
||||||
/* TOOD: Consider unifying _collections and _initializedRelations */
|
/* TODO: Consider unifying _collections and _initializedRelations */
|
||||||
/** Collections initialized by the hydrator */
|
/** Collections initialized by the hydrator */
|
||||||
private $_collections = array();
|
private $_collections = array();
|
||||||
/** Memory for initialized relations */
|
/** Memory for initialized relations */
|
||||||
@ -42,16 +42,19 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
private $_classMetadatas = array();
|
private $_classMetadatas = array();
|
||||||
private $_rootAliases = array();
|
private $_rootAliases = array();
|
||||||
private $_isSimpleQuery = false;
|
private $_isSimpleQuery = false;
|
||||||
|
private $_allowPartialObjects = false;
|
||||||
private $_identifierMap = array();
|
private $_identifierMap = array();
|
||||||
private $_resultPointers = array();
|
private $_resultPointers = array();
|
||||||
private $_idTemplate = array();
|
private $_idTemplate = array();
|
||||||
private $_resultCounter = 0;
|
private $_resultCounter = 0;
|
||||||
private $_discriminatorMap = array();
|
private $_discriminatorMap = array();
|
||||||
|
private $_fetchedAssociations = array();
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
protected function _prepare()
|
protected function _prepare()
|
||||||
{
|
{
|
||||||
$this->_isSimpleQuery = $this->_resultSetMapping->getEntityResultCount() <= 1;
|
$this->_isSimpleQuery = $this->_resultSetMapping->getEntityResultCount() <= 1;
|
||||||
|
$this->_allowPartialObjects = $this->_em->getConfiguration()->getAllowPartialObjects();
|
||||||
$this->_identifierMap = array();
|
$this->_identifierMap = array();
|
||||||
$this->_resultPointers = array();
|
$this->_resultPointers = array();
|
||||||
$this->_idTemplate = array();
|
$this->_idTemplate = array();
|
||||||
@ -64,10 +67,24 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) {
|
if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) {
|
||||||
$this->_discriminatorMap[$class->getClassName()][$class->getDiscriminatorValue()] = $class->getClassName();
|
$this->_discriminatorMap[$class->getClassName()][$class->getDiscriminatorValue()] = $class->getClassName();
|
||||||
foreach (array_merge($class->getParentClasses(), $class->getSubclasses()) as $className) {
|
foreach (array_merge($class->getParentClasses(), $class->getSubclasses()) as $className) {
|
||||||
$value = $this->_em->getClassMetadata($className)->getDiscriminatorValue();
|
$otherClass = $this->_em->getClassMetadata($className);
|
||||||
|
$value = $otherClass->getDiscriminatorValue();
|
||||||
|
$this->_classMetadatas[$className] = $otherClass;
|
||||||
$this->_discriminatorMap[$class->getClassName()][$value] = $className;
|
$this->_discriminatorMap[$class->getClassName()][$value] = $className;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($this->_resultSetMapping->isRelation($dqlAlias)) {
|
||||||
|
$assoc = $this->_resultSetMapping->getRelation($dqlAlias);
|
||||||
|
$this->_fetchedAssociations[$assoc->getSourceEntityName()][$assoc->getSourceFieldName()] = true;
|
||||||
|
if ($mappedByField = $assoc->getMappedByFieldName()) {
|
||||||
|
$this->_fetchedAssociations[$assoc->getTargetEntityName()][$mappedByField] = true;
|
||||||
|
} else if ($inverseAssoc = $this->_em->getClassMetadata($assoc->getTargetEntityName())
|
||||||
|
->getInverseAssociationMapping($assoc->getSourceFieldName())) {
|
||||||
|
$this->_fetchedAssociations[$assoc->getTargetEntityName()][
|
||||||
|
$inverseAssoc->getSourceFieldName()
|
||||||
|
] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,16 +127,15 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the result pointer for an Entity. The result pointers point to the
|
* Updates the result pointer for an entity. The result pointers point to the
|
||||||
* last seen instance of each Entity type. This is used for graph construction.
|
* last seen instance of each entity type. This is used for graph construction.
|
||||||
*
|
*
|
||||||
* @param array $resultPointers The result pointers.
|
* @param array $resultPointers The result pointers.
|
||||||
* @param Collection $coll The element.
|
* @param Collection $coll The element.
|
||||||
* @param boolean|integer $index Index of the element in the collection.
|
* @param boolean|integer $index Index of the element in the collection.
|
||||||
* @param string $dqlAlias
|
* @param string $dqlAlias
|
||||||
* @param boolean $oneToOne Whether it is a single-valued association or not.
|
|
||||||
*/
|
*/
|
||||||
private function updateResultPointer(&$coll, $index, $dqlAlias/*, $oneToOne*/)
|
private function updateResultPointer(&$coll, $index, $dqlAlias)
|
||||||
{
|
{
|
||||||
if ($coll === null) {
|
if ($coll === null) {
|
||||||
unset($this->_resultPointers[$dqlAlias]); // Ticket #1228
|
unset($this->_resultPointers[$dqlAlias]); // Ticket #1228
|
||||||
@ -169,7 +185,7 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
|
|
||||||
$relation = $classMetadata->getAssociationMapping($name);
|
$relation = $classMetadata->getAssociationMapping($name);
|
||||||
$relatedClass = $this->_em->getClassMetadata($relation->getTargetEntityName());
|
$relatedClass = $this->_em->getClassMetadata($relation->getTargetEntityName());
|
||||||
$coll = $this->getCollection($relatedClass->getClassName());
|
$coll = $this->getCollection($relatedClass);
|
||||||
$coll->setOwner($entity, $relation);
|
$coll->setOwner($entity, $relation);
|
||||||
|
|
||||||
$classMetadata->getReflectionProperty($name)->setValue($entity, $coll);
|
$classMetadata->getReflectionProperty($name)->setValue($entity, $coll);
|
||||||
@ -179,6 +195,14 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
return $coll;
|
return $coll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param <type> $entity
|
||||||
|
* @param <type> $assocField
|
||||||
|
* @param <type> $indexField
|
||||||
|
* @return <type>
|
||||||
|
* @todo Consider inlining this method.
|
||||||
|
*/
|
||||||
private function isIndexKeyInUse($entity, $assocField, $indexField)
|
private function isIndexKeyInUse($entity, $assocField, $indexField)
|
||||||
{
|
{
|
||||||
return $this->_classMetadatas[get_class($entity)]
|
return $this->_classMetadatas[get_class($entity)]
|
||||||
@ -207,6 +231,30 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
unset($data[$discrColumn]);
|
unset($data[$discrColumn]);
|
||||||
}
|
}
|
||||||
$entity = $this->_uow->createEntity($className, $data);
|
$entity = $this->_uow->createEntity($className, $data);
|
||||||
|
|
||||||
|
// Properly initialize any unfetched associations, if partial objects are not allowed.
|
||||||
|
if ( ! $this->_allowPartialObjects) {
|
||||||
|
foreach ($this->_classMetadatas[$className]->getAssociationMappings() as $field => $assoc) {
|
||||||
|
if ( ! isset($this->_fetchedAssociations[$className][$field])) {
|
||||||
|
if ($assoc->isOneToOne()) {
|
||||||
|
if ($assoc->isLazilyFetched()) {
|
||||||
|
// Inject proxy
|
||||||
|
$proxy = $this->_em->getProxyGenerator()->getAssociationProxy($entity, $assoc);
|
||||||
|
$this->_classMetadatas[$className]->setFieldValue($entity, $field, $proxy);
|
||||||
|
} else {
|
||||||
|
//TODO: Schedule for eager fetching?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Inject collection
|
||||||
|
$this->_classMetadatas[$className]->getReflectionProperty($field)
|
||||||
|
->setValue($entity, new PersistentCollection($this->_em,
|
||||||
|
$this->_em->getClassMetadata($assoc->getTargetEntityName())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,24 +281,21 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
*/
|
*/
|
||||||
private function setRelatedElement($entity1, $property, $entity2)
|
private function setRelatedElement($entity1, $property, $entity2)
|
||||||
{
|
{
|
||||||
$oid = spl_object_hash($entity1);
|
|
||||||
$classMetadata1 = $this->_classMetadatas[get_class($entity1)];
|
$classMetadata1 = $this->_classMetadatas[get_class($entity1)];
|
||||||
$classMetadata1->getReflectionProperty($property)->setValue($entity1, $entity2);
|
$classMetadata1->getReflectionProperty($property)->setValue($entity1, $entity2);
|
||||||
$this->_uow->setOriginalEntityProperty($oid, $property, $entity2);
|
$this->_uow->setOriginalEntityProperty(spl_object_hash($entity1), $property, $entity2);
|
||||||
$relation = $classMetadata1->getAssociationMapping($property);
|
$relation = $classMetadata1->getAssociationMapping($property);
|
||||||
if ($relation->isOneToOne()) {
|
if ($relation->isOneToOne()) {
|
||||||
$targetClass = $this->_classMetadatas[$relation->getTargetEntityName()];
|
$targetClass = $this->_classMetadatas[$relation->getTargetEntityName()];
|
||||||
if ($relation->isOwningSide()) {
|
if ($relation->isOwningSide()) {
|
||||||
// If there is an inverse mapping on the target class its bidirectional
|
// If there is an inverse mapping on the target class its bidirectional
|
||||||
if ($targetClass->hasInverseAssociationMapping($property)) {
|
if ($targetClass->hasInverseAssociationMapping($property)) {
|
||||||
$oid2 = spl_object_hash($entity2);
|
|
||||||
$sourceProp = $targetClass->getInverseAssociationMapping($fieldName)->getSourceFieldName();
|
$sourceProp = $targetClass->getInverseAssociationMapping($fieldName)->getSourceFieldName();
|
||||||
$targetClass->getReflectionProperty($sourceProp)->setValue($entity2, $entity1);
|
$targetClass->getReflectionProperty($sourceProp)->setValue($entity2, $entity1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// For sure bidirectional, as there is no inverse side in unidirectional
|
// For sure bidirectional, as there is no inverse side in unidirectional
|
||||||
$mappedByProp = $relation->getMappedByFieldName();
|
$targetClass->getReflectionProperty($relation->getMappedByFieldName())->setValue($entity2, $entity1);
|
||||||
$targetClass->getReflectionProperty($mappedByProp)->setValue($entity2, $entity1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,7 +329,6 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
$parent = $this->_resultSetMapping->getParentAlias($dqlAlias);
|
$parent = $this->_resultSetMapping->getParentAlias($dqlAlias);
|
||||||
$relation = $this->_resultSetMapping->getRelation($dqlAlias);
|
$relation = $this->_resultSetMapping->getRelation($dqlAlias);
|
||||||
$relationAlias = $relation->getSourceFieldName();
|
$relationAlias = $relation->getSourceFieldName();
|
||||||
$path = $parent . '.' . $dqlAlias;
|
|
||||||
|
|
||||||
// Get a reference to the right element in the result tree.
|
// Get a reference to the right element in the result tree.
|
||||||
// This element will get the associated element attached.
|
// This element will get the associated element attached.
|
||||||
@ -305,10 +349,10 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
if ( ! $relation->isOneToOne()) {
|
if ( ! $relation->isOneToOne()) {
|
||||||
if (isset($nonemptyComponents[$dqlAlias])) {
|
if (isset($nonemptyComponents[$dqlAlias])) {
|
||||||
if ( ! isset($this->_initializedRelations[spl_object_hash($baseElement)][$relationAlias])) {
|
if ( ! isset($this->_initializedRelations[spl_object_hash($baseElement)][$relationAlias])) {
|
||||||
$this->initRelatedCollection($baseElement, $relationAlias)
|
$this->initRelatedCollection($baseElement, $relationAlias)->setHydrationFlag(true);
|
||||||
->setHydrationFlag(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$path = $parent . '.' . $dqlAlias;
|
||||||
$indexExists = isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]);
|
$indexExists = isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]);
|
||||||
$index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
|
$index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
|
||||||
$indexIsValid = $index !== false ? $this->isIndexKeyInUse($baseElement, $relationAlias, $index) : false;
|
$indexIsValid = $index !== false ? $this->isIndexKeyInUse($baseElement, $relationAlias, $index) : false;
|
||||||
@ -318,17 +362,18 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
// If it's a bi-directional many-to-many, also initialize the reverse collection.
|
// If it's a bi-directional many-to-many, also initialize the reverse collection.
|
||||||
if ($relation->isManyToMany()) {
|
if ($relation->isManyToMany()) {
|
||||||
if ($relation->isOwningSide()) {
|
if ($relation->isOwningSide()) {
|
||||||
$reverseFieldName = $this->_classMetadatas[get_class($element)]
|
$reverseAssoc = $this->_classMetadatas[$entityName]
|
||||||
->getInverseAssociationMapping($relationAlias)
|
->getInverseAssociationMapping($relationAlias);
|
||||||
->getSourceFieldName();
|
if ($reverseAssoc) {
|
||||||
$this->initRelatedCollection($element, $reverseFieldName);
|
$this->initRelatedCollection($element, $reverseAssoc->getSourceFieldName());
|
||||||
|
}
|
||||||
} else if ($mappedByField = $relation->getMappedByFieldName()) {
|
} else if ($mappedByField = $relation->getMappedByFieldName()) {
|
||||||
$this->initRelatedCollection($element, $mappedByField);
|
$this->initRelatedCollection($element, $mappedByField);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($field = $this->_getCustomIndexField($dqlAlias)) {
|
if ($field = $this->_getCustomIndexField($dqlAlias)) {
|
||||||
$indexValue = $this->_classMetadatas[get_class($element)]
|
$indexValue = $this->_classMetadatas[$entityName]
|
||||||
->getReflectionProperty($field)
|
->getReflectionProperty($field)
|
||||||
->getValue($element);
|
->getValue($element);
|
||||||
$this->_classMetadatas[$parentClass]
|
$this->_classMetadatas[$parentClass]
|
||||||
@ -348,17 +393,15 @@ class ObjectHydrator extends AbstractHydrator
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if ( ! $this->isFieldSet($baseElement, $relationAlias)) {
|
} else if ( ! $this->isFieldSet($baseElement, $relationAlias)) {
|
||||||
$coll = new PersistentCollection($this->_em, $entityName);
|
$coll = new PersistentCollection($this->_em, $this->_classMetadatas[$entityName]);
|
||||||
$this->_collections[] = $coll;
|
$this->_collections[] = $coll;
|
||||||
$this->setRelatedElement($baseElement, $relationAlias, $coll);
|
$this->setRelatedElement($baseElement, $relationAlias, $coll);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( ! isset($nonemptyComponents[$dqlAlias]) &&
|
if ( ! isset($nonemptyComponents[$dqlAlias]) && ! $this->isFieldSet($baseElement, $relationAlias)) {
|
||||||
! $this->isFieldSet($baseElement, $relationAlias)) {
|
|
||||||
$this->setRelatedElement($baseElement, $relationAlias, null);
|
$this->setRelatedElement($baseElement, $relationAlias, null);
|
||||||
} else if ( ! $this->isFieldSet($baseElement, $relationAlias)) {
|
} else if ( ! $this->isFieldSet($baseElement, $relationAlias)) {
|
||||||
$this->setRelatedElement($baseElement, $relationAlias,
|
$this->setRelatedElement($baseElement, $relationAlias, $this->getEntity($data, $entityName));
|
||||||
$this->getEntity($data, $entityName));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,8 @@ abstract class AssociationMapping
|
|||||||
'none',
|
'none',
|
||||||
'save',
|
'save',
|
||||||
'delete',
|
'delete',
|
||||||
'refresh'
|
'refresh',
|
||||||
|
'merge'
|
||||||
);
|
);
|
||||||
|
|
||||||
protected $_cascades = array();
|
protected $_cascades = array();
|
||||||
@ -381,5 +382,5 @@ abstract class AssociationMapping
|
|||||||
* @param <type> $entity
|
* @param <type> $entity
|
||||||
* @param <type> $entityManager
|
* @param <type> $entityManager
|
||||||
*/
|
*/
|
||||||
abstract public function lazyLoadFor($entity, $entityManager);
|
/*abstract*/ public function load($entity, $em) {}
|
||||||
}
|
}
|
@ -421,6 +421,7 @@ final class ClassMetadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Gets the change tracking policy used by this class.
|
||||||
*
|
*
|
||||||
* @return integer
|
* @return integer
|
||||||
*/
|
*/
|
||||||
@ -430,6 +431,7 @@ final class ClassMetadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the change tracking policy used by this class.
|
||||||
*
|
*
|
||||||
* @param integer $policy
|
* @param integer $policy
|
||||||
*/
|
*/
|
||||||
@ -439,6 +441,7 @@ final class ClassMetadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Whether the change tracking policy of this class is "deferred explicit".
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
@ -448,6 +451,7 @@ final class ClassMetadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Whether the change tracking policy of this class is "deferred implicit".
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
@ -457,6 +461,7 @@ final class ClassMetadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Whether the change tracking policy of this class is "notify".
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
@ -649,10 +654,8 @@ final class ClassMetadata
|
|||||||
*/
|
*/
|
||||||
public function getInverseAssociationMapping($mappedByFieldName)
|
public function getInverseAssociationMapping($mappedByFieldName)
|
||||||
{
|
{
|
||||||
if ( ! isset($this->_inverseMappings[$mappedByFieldName])) {
|
return isset($this->_inverseMappings[$mappedByFieldName]) ?
|
||||||
throw MappingException::mappingNotFound($mappedByFieldName);
|
$this->_inverseMappings[$mappedByFieldName] : null;
|
||||||
}
|
|
||||||
return $this->_inverseMappings[$mappedByFieldName];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -741,9 +744,9 @@ final class ClassMetadata
|
|||||||
throw MappingException::missingType();
|
throw MappingException::missingType();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! is_object($mapping['type'])) {
|
/*if ( ! is_object($mapping['type'])) {
|
||||||
$mapping['type'] = \Doctrine\DBAL\Types\Type::getType($mapping['type']);
|
$mapping['type'] = \Doctrine\DBAL\Types\Type::getType($mapping['type']);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Complete fieldName and columnName mapping
|
// Complete fieldName and columnName mapping
|
||||||
if ( ! isset($mapping['columnName'])) {
|
if ( ! isset($mapping['columnName'])) {
|
||||||
@ -879,12 +882,12 @@ final class ClassMetadata
|
|||||||
* @param string $field
|
* @param string $field
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
*/
|
*/
|
||||||
public function setValue($entity, $field, $value)
|
/*public function setValue($entity, $field, $value)
|
||||||
{
|
{
|
||||||
if (isset($this->_reflectionProperties[$field])) {
|
if (isset($this->_reflectionProperties[$field])) {
|
||||||
$this->_reflectionProperties[$field]->setValue($entity, $value);
|
$this->_reflectionProperties[$field]->setValue($entity, $value);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the identifier values of an entity of this class.
|
* Extracts the identifier values of an entity of this class.
|
||||||
@ -913,6 +916,7 @@ final class ClassMetadata
|
|||||||
*
|
*
|
||||||
* @param object $entity
|
* @param object $entity
|
||||||
* @param mixed $id
|
* @param mixed $id
|
||||||
|
* @todo Rename to assignIdentifier()
|
||||||
*/
|
*/
|
||||||
public function setIdentifierValues($entity, $id)
|
public function setIdentifierValues($entity, $id)
|
||||||
{
|
{
|
||||||
@ -924,6 +928,30 @@ final class ClassMetadata
|
|||||||
$this->_reflectionProperties[$this->_identifier[0]]->setValue($entity, $id);
|
$this->_reflectionProperties[$this->_identifier[0]]->setValue($entity, $id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the specified field to the specified value on the given entity.
|
||||||
|
*
|
||||||
|
* @param object $entity
|
||||||
|
* @param string $field
|
||||||
|
* @param mixed $value
|
||||||
|
*/
|
||||||
|
public function setFieldValue($entity, $field, $value)
|
||||||
|
{
|
||||||
|
$this->_reflectionProperties[$field]->setValue($entity, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the field mapped to the specified column to the specified value on the given entity.
|
||||||
|
*
|
||||||
|
* @param object $entity
|
||||||
|
* @param string $field
|
||||||
|
* @param mixed $value
|
||||||
|
*/
|
||||||
|
public function setColumnValue($entity, $column, $value)
|
||||||
|
{
|
||||||
|
$this->_reflectionProperties[$this->_fieldNames[$column]]->setValue($entity, $value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all field mappings.
|
* Gets all field mappings.
|
||||||
|
@ -98,6 +98,16 @@ class ClassMetadataFactory
|
|||||||
}
|
}
|
||||||
return $this->_loadedMetadata[$className];
|
return $this->_loadedMetadata[$className];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param <type> $className
|
||||||
|
* @param <type> $class
|
||||||
|
*/
|
||||||
|
public function setMetadataFor($className, $class)
|
||||||
|
{
|
||||||
|
$this->_loadedMetadata[$className] = $class;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the metadata of the class in question and all it's ancestors whose metadata
|
* Loads the metadata of the class in question and all it's ancestors whose metadata
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
*
|
*
|
||||||
* This software consists of voluntary contributions made by many individuals
|
* This software consists of voluntary contributions made by many individuals
|
||||||
* and is licensed under the LGPL. For more information, see
|
* and is licensed under the LGPL. For more information, see
|
||||||
* <http://www.phpdoctrine.org>.
|
* <http://www.doctrine-project.org>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Doctrine\ORM\Mapping;
|
namespace Doctrine\ORM\Mapping;
|
||||||
@ -140,27 +140,37 @@ class OneToOneMapping extends AssociationMapping
|
|||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*
|
*
|
||||||
* @param Doctrine\ORM\Entity $entity
|
* @param object $owningEntity
|
||||||
* @return void
|
* @param object $targetEntity
|
||||||
|
* @param EntityManager $em
|
||||||
*/
|
*/
|
||||||
public function lazyLoadFor($entity, $entityManager)
|
public function load($owningEntity, $targetEntity, $em)
|
||||||
{
|
{
|
||||||
$sourceClass = $entityManager->getClassMetadata($this->_sourceEntityName);
|
$sourceClass = $em->getClassMetadata($this->_sourceEntityName);
|
||||||
$targetClass = $entityManager->getClassMetadata($this->_targetEntityName);
|
$targetClass = $em->getClassMetadata($this->_targetEntityName);
|
||||||
|
|
||||||
$dql = 'SELECT t FROM ' . $targetClass->getClassName() . ' t WHERE ';
|
|
||||||
$params = array();
|
|
||||||
foreach ($this->_sourceToTargetKeyFields as $sourceKeyField => $targetKeyField) {
|
|
||||||
if ($params) $dql .= " AND ";
|
|
||||||
$dql .= "t.$targetKeyField = ?";
|
|
||||||
$params[] = $sourceClass->getReflectionProperty($sourceKeyField)->getValue($entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
$otherEntity = $entityManager->query($dql, $params)->getFirst();
|
$conditions = array();
|
||||||
|
|
||||||
if ( ! $otherEntity) {
|
if ($this->_isOwningSide) {
|
||||||
$otherEntity = null;
|
foreach ($this->_sourceToTargetKeyColumns as $sourceKeyColumn => $targetKeyColumn) {
|
||||||
|
$conditions[$targetKeyColumn] = $sourceClass->getReflectionProperty(
|
||||||
|
$sourceClass->getFieldName($sourceKeyColumn))->getValue($owningEntity);
|
||||||
|
}
|
||||||
|
if ($targetClass->hasInverseAssociation($this->_sourceFieldName)) {
|
||||||
|
$targetClass->setFieldValue(
|
||||||
|
$targetEntity,
|
||||||
|
$targetClass->getInverseAssociationMapping($this->_sourceFieldName)->getSourceFieldName(),
|
||||||
|
$owningEntity);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$owningAssoc = $em->getClassMetadata($this->_targetEntityName)->getAssociationMapping($this->_mappedByFieldName);
|
||||||
|
foreach ($owningAssoc->getTargetToSourceKeyColumns() as $targetKeyColumn => $sourceKeyColumn) {
|
||||||
|
$conditions[$sourceKeyColumn] = $sourceClass->getReflectionProperty(
|
||||||
|
$sourceClass->getFieldName($targetKeyColumn))->getValue($owningEntity);
|
||||||
|
}
|
||||||
|
$targetClass->setFieldValue($targetEntity, $this->_mappedByFieldName, $owningEntity);
|
||||||
}
|
}
|
||||||
$sourceClass->getReflectionProperty($this->_sourceFieldName)->setValue($entity, $otherEntity);
|
|
||||||
|
$em->getUnitOfWork()->getEntityPersister($this->_targetEntityName)->load($conditions, $targetEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -120,18 +120,12 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
|
|||||||
/**
|
/**
|
||||||
* Creates a new persistent collection.
|
* Creates a new persistent collection.
|
||||||
*/
|
*/
|
||||||
public function __construct(EntityManager $em, $type, array $data = array(), $keyField = null)
|
public function __construct(EntityManager $em, $class, array $data = array())
|
||||||
{
|
{
|
||||||
parent::__construct($data);
|
parent::__construct($data);
|
||||||
$this->_type = $type;
|
$this->_type = $class->getClassName();
|
||||||
$this->_em = $em;
|
$this->_em = $em;
|
||||||
$this->_ownerClass = $em->getClassMetadata($type);
|
$this->_ownerClass = $class;
|
||||||
if ($keyField !== null) {
|
|
||||||
if ( ! $this->_ownerClass->hasField($keyField)) {
|
|
||||||
throw DoctrineException::updateMe("Invalid field '$keyField' can't be used as key.");
|
|
||||||
}
|
|
||||||
$this->_keyField = $keyField;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +21,9 @@
|
|||||||
|
|
||||||
namespace Doctrine\ORM\Persisters;
|
namespace Doctrine\ORM\Persisters;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Types\Type;
|
||||||
use Doctrine\ORM\EntityManager;
|
use Doctrine\ORM\EntityManager;
|
||||||
|
use Doctrine\ORM\PersistentCollection;
|
||||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,7 +42,7 @@ abstract class AbstractEntityPersister
|
|||||||
*
|
*
|
||||||
* @var Doctrine\ORM\Mapping\ClassMetadata
|
* @var Doctrine\ORM\Mapping\ClassMetadata
|
||||||
*/
|
*/
|
||||||
protected $_classMetadata;
|
protected $_class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the entity the persister is used for.
|
* The name of the entity the persister is used for.
|
||||||
@ -75,12 +77,12 @@ abstract class AbstractEntityPersister
|
|||||||
* that uses the given EntityManager and persists instances of the class described
|
* that uses the given EntityManager and persists instances of the class described
|
||||||
* by the given class metadata descriptor.
|
* by the given class metadata descriptor.
|
||||||
*/
|
*/
|
||||||
public function __construct(EntityManager $em, ClassMetadata $classMetadata)
|
public function __construct(EntityManager $em, ClassMetadata $class)
|
||||||
{
|
{
|
||||||
$this->_em = $em;
|
$this->_em = $em;
|
||||||
$this->_entityName = $classMetadata->getClassName();
|
$this->_entityName = $class->getClassName();
|
||||||
$this->_conn = $em->getConnection();
|
$this->_conn = $em->getConnection();
|
||||||
$this->_classMetadata = $classMetadata;
|
$this->_class = $class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,8 +96,8 @@ abstract class AbstractEntityPersister
|
|||||||
{
|
{
|
||||||
$insertData = array();
|
$insertData = array();
|
||||||
$this->_prepareData($entity, $insertData, true);
|
$this->_prepareData($entity, $insertData, true);
|
||||||
$this->_conn->insert($this->_classMetadata->getTableName(), $insertData);
|
$this->_conn->insert($this->_class->getTableName(), $insertData);
|
||||||
$idGen = $this->_classMetadata->getIdGenerator();
|
$idGen = $this->_class->getIdGenerator();
|
||||||
if ($idGen->isPostInsertGenerator()) {
|
if ($idGen->isPostInsertGenerator()) {
|
||||||
return $idGen->generate($this->_em, $entity);
|
return $idGen->generate($this->_em, $entity);
|
||||||
}
|
}
|
||||||
@ -119,8 +121,8 @@ abstract class AbstractEntityPersister
|
|||||||
*/
|
*/
|
||||||
public function executeInserts()
|
public function executeInserts()
|
||||||
{
|
{
|
||||||
//$tableName = $this->_classMetadata->getTableName();
|
//$tableName = $this->_class->getTableName();
|
||||||
$stmt = $this->_conn->prepare($this->_classMetadata->getInsertSql());
|
$stmt = $this->_conn->prepare($this->_class->getInsertSql());
|
||||||
foreach ($this->_queuedInserts as $insertData) {
|
foreach ($this->_queuedInserts as $insertData) {
|
||||||
$stmt->execute(array_values($insertData));
|
$stmt->execute(array_values($insertData));
|
||||||
}
|
}
|
||||||
@ -136,9 +138,9 @@ abstract class AbstractEntityPersister
|
|||||||
{
|
{
|
||||||
$updateData = array();
|
$updateData = array();
|
||||||
$this->_prepareData($entity, $updateData);
|
$this->_prepareData($entity, $updateData);
|
||||||
$id = array_combine($this->_classMetadata->getIdentifierFieldNames(),
|
$id = array_combine($this->_class->getIdentifierFieldNames(),
|
||||||
$this->_em->getUnitOfWork()->getEntityIdentifier($entity));
|
$this->_em->getUnitOfWork()->getEntityIdentifier($entity));
|
||||||
$this->_conn->update($this->_classMetadata->getTableName(), $updateData, $id);
|
$this->_conn->update($this->_class->getTableName(), $updateData, $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,10 +151,10 @@ abstract class AbstractEntityPersister
|
|||||||
public function delete($entity)
|
public function delete($entity)
|
||||||
{
|
{
|
||||||
$id = array_combine(
|
$id = array_combine(
|
||||||
$this->_classMetadata->getIdentifierFieldNames(),
|
$this->_class->getIdentifierFieldNames(),
|
||||||
$this->_em->getUnitOfWork()->getEntityIdentifier($entity)
|
$this->_em->getUnitOfWork()->getEntityIdentifier($entity)
|
||||||
);
|
);
|
||||||
$this->_conn->delete($this->_classMetadata->getTableName(), $id);
|
$this->_conn->delete($this->_class->getTableName(), $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,7 +184,7 @@ abstract class AbstractEntityPersister
|
|||||||
*/
|
*/
|
||||||
public function getClassMetadata()
|
public function getClassMetadata()
|
||||||
{
|
{
|
||||||
return $this->_classMetadata;
|
return $this->_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -221,12 +223,11 @@ abstract class AbstractEntityPersister
|
|||||||
foreach ($this->_em->getUnitOfWork()->getEntityChangeSet($entity) as $field => $change) {
|
foreach ($this->_em->getUnitOfWork()->getEntityChangeSet($entity) as $field => $change) {
|
||||||
$oldVal = $change[0];
|
$oldVal = $change[0];
|
||||||
$newVal = $change[1];
|
$newVal = $change[1];
|
||||||
|
|
||||||
$type = $this->_classMetadata->getTypeOfField($field);
|
|
||||||
$columnName = $this->_classMetadata->getColumnName($field);
|
|
||||||
|
|
||||||
if ($this->_classMetadata->hasAssociation($field)) {
|
$columnName = $this->_class->getColumnName($field);
|
||||||
$assocMapping = $this->_classMetadata->getAssociationMapping($field);
|
|
||||||
|
if ($this->_class->hasAssociation($field)) {
|
||||||
|
$assocMapping = $this->_class->getAssociationMapping($field);
|
||||||
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
|
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -242,8 +243,94 @@ abstract class AbstractEntityPersister
|
|||||||
} else if ($newVal === null) {
|
} else if ($newVal === null) {
|
||||||
$result[$columnName] = null;
|
$result[$columnName] = null;
|
||||||
} else {
|
} else {
|
||||||
$result[$columnName] = $type->convertToDatabaseValue($newVal, $this->_conn->getDatabasePlatform());
|
$result[$columnName] = Type::getType($this->_class->getTypeOfField($field))
|
||||||
|
->convertToDatabaseValue($newVal, $this->_conn->getDatabasePlatform());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an entity by a list of field criteria.
|
||||||
|
*
|
||||||
|
* @param array $criteria The criteria by which to load the entity.
|
||||||
|
* @param object $entity The entity to load the data into. If not specified,
|
||||||
|
* a new entity is created.
|
||||||
|
*/
|
||||||
|
public function load(array $criteria, $entity = null)
|
||||||
|
{
|
||||||
|
$stmt = $this->_conn->prepare($this->_getSelectSingleEntitySql($criteria));
|
||||||
|
$stmt->execute(array_values($criteria));
|
||||||
|
$data = array();
|
||||||
|
foreach ($stmt->fetch(\PDO::FETCH_ASSOC) as $column => $value) {
|
||||||
|
$fieldName = $this->_class->getFieldNameForLowerColumnName($column);
|
||||||
|
$data[$fieldName] = Type::getType($this->_class->getTypeOfField($fieldName))
|
||||||
|
->convertToPHPValue($value);
|
||||||
|
}
|
||||||
|
$stmt->closeCursor();
|
||||||
|
|
||||||
|
if ($entity === null) {
|
||||||
|
$entity = $this->_em->getUnitOfWork()->createEntity($this->_entityName, $data);
|
||||||
|
} else {
|
||||||
|
foreach ($data as $field => $value) {
|
||||||
|
$this->_class->setFieldValue($entity, $field, $value);
|
||||||
|
}
|
||||||
|
$id = array();
|
||||||
|
if ($this->_class->isIdentifierComposite()) {
|
||||||
|
$identifierFieldNames = $this->_class->getIdentifier();
|
||||||
|
foreach ($identifierFieldNames as $fieldName) {
|
||||||
|
$id[] = $data[$fieldName];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$id = array($data[$this->_class->getSingleIdentifierFieldName()]);
|
||||||
|
}
|
||||||
|
$this->_em->getUnitOfWork()->registerManaged($entity, $id, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! $this->_em->getConfiguration()->getAllowPartialObjects()) {
|
||||||
|
foreach ($this->_class->getAssociationMappings() as $field => $assoc) {
|
||||||
|
if ($assoc->isOneToOne()) {
|
||||||
|
if ($assoc->isLazilyFetched()) {
|
||||||
|
// Inject proxy
|
||||||
|
$proxy = $this->_em->getProxyGenerator()->getAssociationProxy($entity, $assoc);
|
||||||
|
$this->_class->setFieldValue($entity, $field, $proxy);
|
||||||
|
} else {
|
||||||
|
//TODO: Eager fetch?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Inject collection
|
||||||
|
$this->_class->getReflectionProperty($field)
|
||||||
|
->setValue($entity, new PersistentCollection($this->_em,
|
||||||
|
$this->_em->getClassMetadata($assoc->getTargetEntityName())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the SELECT SQL to select a single entity by a set of field criteria.
|
||||||
|
*
|
||||||
|
* @param array $criteria
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function _getSelectSingleEntitySql(array $criteria)
|
||||||
|
{
|
||||||
|
$columnList = '';
|
||||||
|
$columnNames = $this->_class->getColumnNames();
|
||||||
|
foreach ($columnNames as $column) {
|
||||||
|
if ($columnList != '') $columnList .= ', ';
|
||||||
|
$columnList .= $column;
|
||||||
|
}
|
||||||
|
|
||||||
|
$conditionSql = '';
|
||||||
|
foreach ($criteria as $field => $value) {
|
||||||
|
if ($conditionSql != '') $conditionSql .= ' AND ';
|
||||||
|
$conditionSql .= $this->_class->getColumnName($field) . ' = ?';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'SELECT ' . $columnList . ' FROM ' . $this->_class->getTableName()
|
||||||
|
. ' WHERE ' . $conditionSql;
|
||||||
|
}
|
||||||
}
|
}
|
@ -26,7 +26,7 @@ use Doctrine\ORM\PersistentCollection;
|
|||||||
/**
|
/**
|
||||||
* Persister for many-to-many collections.
|
* Persister for many-to-many collections.
|
||||||
*
|
*
|
||||||
* @author robo
|
* @author Roman Borschel <roman@code-factory.org>
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
class ManyToManyPersister extends AbstractCollectionPersister
|
class ManyToManyPersister extends AbstractCollectionPersister
|
||||||
@ -41,7 +41,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
$joinTable = $mapping->getJoinTable();
|
$joinTable = $mapping->getJoinTable();
|
||||||
$columns = $mapping->getJoinTableColumns();
|
$columns = $mapping->getJoinTableColumns();
|
||||||
return "DELETE FROM {$joinTable['name']} WHERE " . implode(' = ? AND ', $columns) . ' = ?';
|
return 'DELETE FROM ' . $joinTable['name'] . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,8 +77,8 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
$mapping = $coll->getMapping();
|
$mapping = $coll->getMapping();
|
||||||
$joinTable = $mapping->getJoinTable();
|
$joinTable = $mapping->getJoinTable();
|
||||||
$columns = $mapping->getJoinTableColumns();
|
$columns = $mapping->getJoinTableColumns();
|
||||||
return "INSERT INTO {$joinTable['name']} (" . implode(', ', $columns) . ")"
|
return 'INSERT INTO ' . $joinTable['name'] . ' (' . implode(', ', $columns) . ')'
|
||||||
. " VALUES (" . implode(', ', array_fill(0, count($columns), '?')) . ')';
|
. ' VALUES (' . implode(', ', array_fill(0, count($columns), '?')) . ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,7 +88,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
*/
|
*/
|
||||||
protected function _getInsertRowSqlParameters(PersistentCollection $coll, $element)
|
protected function _getInsertRowSqlParameters(PersistentCollection $coll, $element)
|
||||||
{
|
{
|
||||||
//FIXME: This is still problematic for composite keys because we silently
|
// FIXME: This is still problematic for composite keys because we silently
|
||||||
// rely on a specific ordering of the columns.
|
// rely on a specific ordering of the columns.
|
||||||
$params = array_merge(
|
$params = array_merge(
|
||||||
$this->_uow->getEntityIdentifier($coll->getOwner()),
|
$this->_uow->getEntityIdentifier($coll->getOwner()),
|
||||||
@ -112,7 +112,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
|||||||
if ($whereClause !== '') $whereClause .= ' AND ';
|
if ($whereClause !== '') $whereClause .= ' AND ';
|
||||||
$whereClause .= "$relationColumn = ?";
|
$whereClause .= "$relationColumn = ?";
|
||||||
}
|
}
|
||||||
return "DELETE FROM {$joinTable['name']} WHERE $whereClause";
|
return 'DELETE FROM ' . $joinTable['name'] . ' WHERE ' . $whereClause;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,19 +33,14 @@ namespace Doctrine\ORM\Persisters;
|
|||||||
*/
|
*/
|
||||||
class SingleTablePersister extends AbstractEntityPersister
|
class SingleTablePersister extends AbstractEntityPersister
|
||||||
{
|
{
|
||||||
public function insert($entity)
|
|
||||||
{
|
|
||||||
return parent::insert($entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
protected function _prepareData($entity, array &$result, $isInsert = false)
|
protected function _prepareData($entity, array &$result, $isInsert = false)
|
||||||
{
|
{
|
||||||
parent::_prepareData($entity, $result, $isInsert);
|
parent::_prepareData($entity, $result, $isInsert);
|
||||||
// Populate the discriminator column
|
// Populate the discriminator column
|
||||||
if ($isInsert) {
|
if ($isInsert) {
|
||||||
$discColumn = $this->_classMetadata->getDiscriminatorColumn();
|
$discColumn = $this->_class->getDiscriminatorColumn();
|
||||||
$result[$discColumn['name']] = $this->_classMetadata->getDiscriminatorValue();
|
$result[$discColumn['name']] = $this->_class->getDiscriminatorValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -165,6 +165,11 @@ class ResultSetMapping
|
|||||||
return $this->_relationMap[$alias];
|
return $this->_relationMap[$alias];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isRelation($alias)
|
||||||
|
{
|
||||||
|
return isset($this->_relationMap[$alias]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param <type> $columnName
|
* @param <type> $columnName
|
||||||
|
@ -158,7 +158,7 @@ class SchemaTool
|
|||||||
foreach ($class->getFieldMappings() as $fieldName => $mapping) {
|
foreach ($class->getFieldMappings() as $fieldName => $mapping) {
|
||||||
$column = array();
|
$column = array();
|
||||||
$column['name'] = $mapping['columnName'];
|
$column['name'] = $mapping['columnName'];
|
||||||
$column['type'] = $mapping['type'];
|
$column['type'] = Type::getType($mapping['type']);
|
||||||
$column['length'] = $mapping['length'];
|
$column['length'] = $mapping['length'];
|
||||||
$column['notnull'] = ! $mapping['nullable'];
|
$column['notnull'] = ! $mapping['nullable'];
|
||||||
if ($class->isIdentifier($fieldName)) {
|
if ($class->isIdentifier($fieldName)) {
|
||||||
@ -187,7 +187,7 @@ class SchemaTool
|
|||||||
foreach ($mapping->getJoinColumns() as $joinColumn) {
|
foreach ($mapping->getJoinColumns() as $joinColumn) {
|
||||||
$column = array();
|
$column = array();
|
||||||
$column['name'] = $joinColumn['name'];
|
$column['name'] = $joinColumn['name'];
|
||||||
$column['type'] = $foreignClass->getTypeOfColumn($joinColumn['referencedColumnName']);
|
$column['type'] = Type::getType($foreignClass->getTypeOfColumn($joinColumn['referencedColumnName']));
|
||||||
$columns[$joinColumn['name']] = $column;
|
$columns[$joinColumn['name']] = $column;
|
||||||
$constraint['local'][] = $joinColumn['name'];
|
$constraint['local'][] = $joinColumn['name'];
|
||||||
$constraint['foreign'][] = $joinColumn['referencedColumnName'];
|
$constraint['foreign'][] = $joinColumn['referencedColumnName'];
|
||||||
@ -211,7 +211,7 @@ class SchemaTool
|
|||||||
$column['primary'] = true;
|
$column['primary'] = true;
|
||||||
$joinTableOptions['primary'][] = $joinColumn['name'];
|
$joinTableOptions['primary'][] = $joinColumn['name'];
|
||||||
$column['name'] = $joinColumn['name'];
|
$column['name'] = $joinColumn['name'];
|
||||||
$column['type'] = $class->getTypeOfColumn($joinColumn['referencedColumnName']);
|
$column['type'] = Type::getType($class->getTypeOfColumn($joinColumn['referencedColumnName']));
|
||||||
$joinTableColumns[$joinColumn['name']] = $column;
|
$joinTableColumns[$joinColumn['name']] = $column;
|
||||||
$constraint1['local'][] = $joinColumn['name'];
|
$constraint1['local'][] = $joinColumn['name'];
|
||||||
$constraint1['foreign'][] = $joinColumn['referencedColumnName'];
|
$constraint1['foreign'][] = $joinColumn['referencedColumnName'];
|
||||||
@ -228,8 +228,8 @@ class SchemaTool
|
|||||||
$column['primary'] = true;
|
$column['primary'] = true;
|
||||||
$joinTableOptions['primary'][] = $inverseJoinColumn['name'];
|
$joinTableOptions['primary'][] = $inverseJoinColumn['name'];
|
||||||
$column['name'] = $inverseJoinColumn['name'];
|
$column['name'] = $inverseJoinColumn['name'];
|
||||||
$column['type'] = $this->_em->getClassMetadata($mapping->getTargetEntityName())
|
$column['type'] = Type::getType($this->_em->getClassMetadata($mapping->getTargetEntityName())
|
||||||
->getTypeOfColumn($inverseJoinColumn['referencedColumnName']);
|
->getTypeOfColumn($inverseJoinColumn['referencedColumnName']));
|
||||||
$joinTableColumns[$inverseJoinColumn['name']] = $column;
|
$joinTableColumns[$inverseJoinColumn['name']] = $column;
|
||||||
$constraint2['local'][] = $inverseJoinColumn['name'];
|
$constraint2['local'][] = $inverseJoinColumn['name'];
|
||||||
$constraint2['foreign'][] = $inverseJoinColumn['referencedColumnName'];
|
$constraint2['foreign'][] = $inverseJoinColumn['referencedColumnName'];
|
||||||
|
@ -400,7 +400,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
$assoc = $class->getAssociationMapping($name);
|
$assoc = $class->getAssociationMapping($name);
|
||||||
//echo PHP_EOL . "INJECTING PCOLL into $name" . PHP_EOL;
|
//echo PHP_EOL . "INJECTING PCOLL into $name" . PHP_EOL;
|
||||||
// Inject PersistentCollection
|
// Inject PersistentCollection
|
||||||
$coll = new PersistentCollection($this->_em, $assoc->getTargetEntityName(),
|
$coll = new PersistentCollection($this->_em, $this->_em->getClassMetadata($assoc->getTargetEntityName()),
|
||||||
$actualData[$name] ? $actualData[$name] : array());
|
$actualData[$name] ? $actualData[$name] : array());
|
||||||
$coll->setOwner($entity, $assoc);
|
$coll->setOwner($entity, $assoc);
|
||||||
if ( ! $coll->isEmpty()) {
|
if ( ! $coll->isEmpty()) {
|
||||||
@ -1298,6 +1298,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* INTERNAL:
|
||||||
* Creates an entity. Used for reconstitution of entities during hydration.
|
* Creates an entity. Used for reconstitution of entities during hydration.
|
||||||
*
|
*
|
||||||
* @param string $className The name of the entity class.
|
* @param string $className The name of the entity class.
|
||||||
@ -1328,13 +1329,6 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
} else {
|
} else {
|
||||||
$entity = new $className;
|
$entity = new $className;
|
||||||
$oid = spl_object_hash($entity);
|
$oid = spl_object_hash($entity);
|
||||||
/*if ($class->hasLazySingleValuedAssociations()) {
|
|
||||||
foreach ($class->getLazyAssociations() as $lazyAssoc) {
|
|
||||||
// Inject VirtualProxy
|
|
||||||
$prop = $class->getReflectionProperty($lazyAssoc->getSourceFieldName());
|
|
||||||
$prop->setValue($entity, new \Doctrine\ORM\VirtualProxy($entity, $lazyAssoc, $prop));
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
$this->_entityIdentifiers[$oid] = $id;
|
$this->_entityIdentifiers[$oid] = $id;
|
||||||
$this->_entityStates[$oid] = self::STATE_MANAGED;
|
$this->_entityStates[$oid] = self::STATE_MANAGED;
|
||||||
$this->_originalEntityData[$oid] = $data;
|
$this->_originalEntityData[$oid] = $data;
|
||||||
@ -1344,7 +1338,9 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
|
|
||||||
if ($overrideLocalChanges) {
|
if ($overrideLocalChanges) {
|
||||||
foreach ($data as $field => $value) {
|
foreach ($data as $field => $value) {
|
||||||
$class->setValue($entity, $field, $value);
|
if ($class->hasField($field)) {
|
||||||
|
$class->setFieldValue($entity, $field, $value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
foreach ($data as $field => $value) {
|
foreach ($data as $field => $value) {
|
||||||
@ -1512,6 +1508,23 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
return $this->_collectionPersisters[$type];
|
return $this->_collectionPersisters[$type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* INTERNAL:
|
||||||
|
* Registers an entity as managed.
|
||||||
|
*
|
||||||
|
* @param object $entity The entity.
|
||||||
|
* @param array $id The identifier values.
|
||||||
|
* @param array $data The original entity data.
|
||||||
|
*/
|
||||||
|
public function registerManaged($entity, $id, $data)
|
||||||
|
{
|
||||||
|
$oid = spl_object_hash($entity);
|
||||||
|
$this->_entityIdentifiers[$oid] = $id;
|
||||||
|
$this->_entityStates[$oid] = self::STATE_MANAGED;
|
||||||
|
$this->_originalEntityData[$oid] = $data;
|
||||||
|
$this->addToIdentityMap($entity);
|
||||||
|
}
|
||||||
|
|
||||||
/* PropertyChangedListener implementation */
|
/* PropertyChangedListener implementation */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,7 +53,7 @@ class VirtualProxy
|
|||||||
|
|
||||||
private function _load()
|
private function _load()
|
||||||
{
|
{
|
||||||
$realInstance = $tis->_assoc->lazyLoadFor($this->_owner);
|
$realInstance = $this->_assoc->lazyLoadFor($this->_owner);
|
||||||
$this->_refProp->setValue($this->_owner, $realInstance);
|
$this->_refProp->setValue($this->_owner, $realInstance);
|
||||||
return $realInstance;
|
return $realInstance;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ class MySqlPlatformTest extends \Doctrine\Tests\DbalTestCase
|
|||||||
'notnull' => true
|
'notnull' => true
|
||||||
),
|
),
|
||||||
'test' => array(
|
'test' => array(
|
||||||
'type' => Type::getType('varchar'),
|
'type' => Type::getType('string'),
|
||||||
'length' => 255,
|
'length' => 255,
|
||||||
'notnull' => true
|
'notnull' => true
|
||||||
)
|
)
|
||||||
|
@ -26,7 +26,7 @@ class PostgreSqlPlatformTest extends \Doctrine\Tests\DbalTestCase
|
|||||||
'notnull' => true
|
'notnull' => true
|
||||||
),
|
),
|
||||||
'test' => array(
|
'test' => array(
|
||||||
'type' => Type::getType('varchar'),
|
'type' => Type::getType('string'),
|
||||||
'length' => 255,
|
'length' => 255,
|
||||||
'notnull' => true
|
'notnull' => true
|
||||||
)
|
)
|
||||||
|
@ -25,7 +25,7 @@ class SqlitePlatformTest extends \Doctrine\Tests\DbalTestCase
|
|||||||
'notnull' => true
|
'notnull' => true
|
||||||
),
|
),
|
||||||
'test' => array(
|
'test' => array(
|
||||||
'type' => new \Doctrine\DBAL\Types\VarcharType,
|
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||||
'length' => 255
|
'length' => 255
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -19,17 +19,17 @@ class CmsAddress
|
|||||||
public $id;
|
public $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=50)
|
* @DoctrineColumn(type="string", length=50)
|
||||||
*/
|
*/
|
||||||
public $country;
|
public $country;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=50)
|
* @DoctrineColumn(type="string", length=50)
|
||||||
*/
|
*/
|
||||||
public $zip;
|
public $zip;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=50)
|
* @DoctrineColumn(type="string", length=50)
|
||||||
*/
|
*/
|
||||||
public $city;
|
public $city;
|
||||||
|
|
||||||
@ -38,4 +38,20 @@ class CmsAddress
|
|||||||
* @DoctrineJoinColumn(name="user_id", referencedColumnName="id")
|
* @DoctrineJoinColumn(name="user_id", referencedColumnName="id")
|
||||||
*/
|
*/
|
||||||
public $user;
|
public $user;
|
||||||
|
|
||||||
|
public function getId() {
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCountry() {
|
||||||
|
return $this->country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getZipCode() {
|
||||||
|
return $this->zip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCity() {
|
||||||
|
return $this->city;
|
||||||
|
}
|
||||||
}
|
}
|
@ -15,11 +15,11 @@ class CmsArticle
|
|||||||
*/
|
*/
|
||||||
public $id;
|
public $id;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=255)
|
* @DoctrineColumn(type="string", length=255)
|
||||||
*/
|
*/
|
||||||
public $topic;
|
public $topic;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar")
|
* @DoctrineColumn(type="string")
|
||||||
*/
|
*/
|
||||||
public $text;
|
public $text;
|
||||||
/**
|
/**
|
||||||
|
@ -15,11 +15,11 @@ class CmsComment
|
|||||||
*/
|
*/
|
||||||
public $id;
|
public $id;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=255)
|
* @DoctrineColumn(type="string", length=255)
|
||||||
*/
|
*/
|
||||||
public $topic;
|
public $topic;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar")
|
* @DoctrineColumn(type="string")
|
||||||
*/
|
*/
|
||||||
public $text;
|
public $text;
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@ class CmsGroup
|
|||||||
*/
|
*/
|
||||||
public $id;
|
public $id;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=50)
|
* @DoctrineColumn(type="string", length=50)
|
||||||
*/
|
*/
|
||||||
public $name;
|
public $name;
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,7 @@ namespace Doctrine\Tests\Models\CMS;
|
|||||||
class CmsPhonenumber
|
class CmsPhonenumber
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=50)
|
* @DoctrineColumn(type="string", length=50)
|
||||||
* @DoctrineId
|
* @DoctrineId
|
||||||
*/
|
*/
|
||||||
public $phonenumber;
|
public $phonenumber;
|
||||||
|
@ -15,15 +15,15 @@ class CmsUser
|
|||||||
*/
|
*/
|
||||||
public $id;
|
public $id;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=50)
|
* @DoctrineColumn(type="string", length=50)
|
||||||
*/
|
*/
|
||||||
public $status;
|
public $status;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=255)
|
* @DoctrineColumn(type="string", length=255)
|
||||||
*/
|
*/
|
||||||
public $username;
|
public $username;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=255)
|
* @DoctrineColumn(type="string", length=255)
|
||||||
*/
|
*/
|
||||||
public $name;
|
public $name;
|
||||||
/**
|
/**
|
||||||
|
@ -6,7 +6,7 @@ namespace Doctrine\Tests\Models\Company;
|
|||||||
* @DoctrineEntity
|
* @DoctrineEntity
|
||||||
* @DoctrineTable(name="company_employee")
|
* @DoctrineTable(name="company_employee")
|
||||||
* @DoctrineInheritanceType("joined")
|
* @DoctrineInheritanceType("joined")
|
||||||
* @DoctrineDiscriminatorColumn(name="dtype", type="varchar", length=20)
|
* @DoctrineDiscriminatorColumn(name="dtype", type="string", length=20)
|
||||||
* @DoctrineDiscriminatorMap({
|
* @DoctrineDiscriminatorMap({
|
||||||
"emp" = "Doctrine\Tests\Models\Company\CompanyEmployee",
|
"emp" = "Doctrine\Tests\Models\Company\CompanyEmployee",
|
||||||
"man" = "Doctrine\Tests\Models\Company\CompanyManager"})
|
"man" = "Doctrine\Tests\Models\Company\CompanyManager"})
|
||||||
@ -27,7 +27,7 @@ class CompanyEmployee
|
|||||||
public $salary;
|
public $salary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=255)
|
* @DoctrineColumn(type="string", length=255)
|
||||||
*/
|
*/
|
||||||
public $department;
|
public $department;
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ namespace Doctrine\Tests\Models\Company;
|
|||||||
class CompanyManager extends CompanyEmployee
|
class CompanyManager extends CompanyEmployee
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* @DoctrineColumn(type="varchar", length="255")
|
* @DoctrineColumn(type="string", length="255")
|
||||||
*/
|
*/
|
||||||
public $title;
|
public $title;
|
||||||
}
|
}
|
@ -18,7 +18,7 @@ class ForumCategory
|
|||||||
*/
|
*/
|
||||||
public $position;
|
public $position;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=255)
|
* @DoctrineColumn(type="string", length=255)
|
||||||
*/
|
*/
|
||||||
public $name;
|
public $name;
|
||||||
/**
|
/**
|
||||||
|
@ -15,7 +15,7 @@ class ForumEntry
|
|||||||
*/
|
*/
|
||||||
public $id;
|
public $id;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=50)
|
* @DoctrineColumn(type="string", length=50)
|
||||||
*/
|
*/
|
||||||
public $topic;
|
public $topic;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ class ForumUser
|
|||||||
*/
|
*/
|
||||||
public $id;
|
public $id;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=50)
|
* @DoctrineColumn(type="string", length=50)
|
||||||
*/
|
*/
|
||||||
public $username;
|
public $username;
|
||||||
/**
|
/**
|
||||||
|
@ -202,8 +202,8 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertEquals('Guilherme', $users[0]->name);
|
$this->assertEquals('Guilherme', $users[0]->name);
|
||||||
$this->assertEquals('gblanco', $users[0]->username);
|
$this->assertEquals('gblanco', $users[0]->username);
|
||||||
$this->assertEquals('developer', $users[0]->status);
|
$this->assertEquals('developer', $users[0]->status);
|
||||||
$this->assertNull($users[0]->phonenumbers);
|
//$this->assertNull($users[0]->phonenumbers);
|
||||||
$this->assertNull($users[0]->articles);
|
//$this->assertNull($users[0]->articles);
|
||||||
|
|
||||||
$usersArray = $query->getResultArray();
|
$usersArray = $query->getResultArray();
|
||||||
|
|
||||||
@ -257,7 +257,7 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertEquals('developer', $users[0]->status);
|
$this->assertEquals('developer', $users[0]->status);
|
||||||
$this->assertTrue($users[0]->phonenumbers instanceof \Doctrine\ORM\PersistentCollection);
|
$this->assertTrue($users[0]->phonenumbers instanceof \Doctrine\ORM\PersistentCollection);
|
||||||
$this->assertEquals(0, $users[0]->phonenumbers->count());
|
$this->assertEquals(0, $users[0]->phonenumbers->count());
|
||||||
$this->assertNull($users[0]->articles);
|
//$this->assertNull($users[0]->articles);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testBasicManyToManyJoin()
|
public function testBasicManyToManyJoin()
|
||||||
@ -307,11 +307,27 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$query = $this->_em->createQuery("select u, g from Doctrine\Tests\Models\CMS\CmsUser u inner join u.groups g");
|
$query = $this->_em->createQuery("select u, g from Doctrine\Tests\Models\CMS\CmsUser u inner join u.groups g");
|
||||||
$this->assertEquals(0, count($query->getResultList()));
|
$this->assertEquals(0, count($query->getResultList()));
|
||||||
|
|
||||||
/* RB: TEST
|
/* RB: TEST */
|
||||||
\Doctrine\ORM\DynamicProxyGenerator::configure($this->_em);
|
/*
|
||||||
$proxy = \Doctrine\ORM\DynamicProxyGenerator::getReferenceProxy('Doctrine\Tests\Models\CMS\CmsUser', 1);
|
$address = new CmsAddress;
|
||||||
echo $proxy->getId();
|
$address->country = 'Germany';
|
||||||
var_dump(serialize($proxy));
|
$address->zip = '103040';
|
||||||
|
$address->city = 'Berlin';
|
||||||
|
$address->user = $user;
|
||||||
|
$this->_em->save($address);
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$proxy = $this->_em->getProxyGenerator()->getAssociationProxy($user, $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser')->getAssociationMapping('address'));
|
||||||
|
|
||||||
|
var_dump($proxy->getId());
|
||||||
|
//var_dump(get_class($proxy));
|
||||||
|
var_dump(get_class($proxy->user));
|
||||||
|
//var_dump($proxy);
|
||||||
|
|
||||||
|
//$proxy = $this->_em->getProxyGenerator()->getReferenceProxy('Doctrine\Tests\Models\CMS\CmsUser', 1);
|
||||||
|
|
||||||
|
//echo $proxy->getId();
|
||||||
|
//var_dump(serialize($proxy));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
/**
|
/**
|
||||||
* @DoctrineEntity
|
* @DoctrineEntity
|
||||||
* @DoctrineInheritanceType("singleTable")
|
* @DoctrineInheritanceType("singleTable")
|
||||||
* @DoctrineDiscriminatorColumn(name="discr", type="varchar")
|
* @DoctrineDiscriminatorColumn(name="discr", type="string")
|
||||||
* @DoctrineSubClasses({"Doctrine\Tests\ORM\Functional\ChildEntity"})
|
* @DoctrineSubClasses({"Doctrine\Tests\ORM\Functional\ChildEntity"})
|
||||||
* @DoctrineDiscriminatorValue("parent")
|
* @DoctrineDiscriminatorValue("parent")
|
||||||
*/
|
*/
|
||||||
@ -107,7 +107,7 @@ class ParentEntity {
|
|||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar")
|
* @DoctrineColumn(type="string")
|
||||||
*/
|
*/
|
||||||
private $data;
|
private $data;
|
||||||
|
|
||||||
@ -168,7 +168,7 @@ class RelatedEntity {
|
|||||||
*/
|
*/
|
||||||
private $id;
|
private $id;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar", length=50)
|
* @DoctrineColumn(type="string", length=50)
|
||||||
*/
|
*/
|
||||||
private $name;
|
private $name;
|
||||||
/**
|
/**
|
||||||
|
@ -194,7 +194,7 @@ class NotifyChangedEntity implements \Doctrine\Common\NotifyPropertyChanged
|
|||||||
*/
|
*/
|
||||||
private $id;
|
private $id;
|
||||||
/**
|
/**
|
||||||
* @DoctrineColumn(type="varchar")
|
* @DoctrineColumn(type="string")
|
||||||
*/
|
*/
|
||||||
private $data;
|
private $data;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user