From cbe4987e18e0be1f5c31ee3106a50325b673f3df Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Fri, 30 Mar 2012 23:15:44 +0200 Subject: [PATCH 1/6] Using Doctrine\Common\Util\ClassUtil for class_name resolutionThis avoids exceptions when passing a Proxy instance to the public API of the EntityManager, ClassMetadataFactory or UnitOfWork when the Proxy itself isn't generated by the EntityManager itself, while discovering the correct ClassMetadata instance for the proxy --- lib/Doctrine/ORM/AbstractQuery.php | 4 +- lib/Doctrine/ORM/Id/AssignedGenerator.php | 3 +- lib/Doctrine/ORM/PersistentCollection.php | 5 +- .../ORM/Persisters/BasicEntityPersister.php | 7 ++- .../ORM/Persisters/ManyToManyPersister.php | 13 ++-- lib/Doctrine/ORM/UnitOfWork.php | 60 +++++++++---------- 6 files changed, 48 insertions(+), 44 deletions(-) diff --git a/lib/Doctrine/ORM/AbstractQuery.php b/lib/Doctrine/ORM/AbstractQuery.php index 07af294b1..333107c73 100644 --- a/lib/Doctrine/ORM/AbstractQuery.php +++ b/lib/Doctrine/ORM/AbstractQuery.php @@ -22,7 +22,7 @@ namespace Doctrine\ORM; use Doctrine\DBAL\Types\Type, Doctrine\DBAL\Cache\QueryCacheProfile, Doctrine\ORM\Query\QueryException, - Doctrine\ORM\Internal\Hydration\CacheHydrator; + Doctrine\Common\Util\ClassUtils; /** * Base contract for ORM queries. Base class for Query and NativeQuery. @@ -241,7 +241,7 @@ abstract class AbstractQuery return $value; - case is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value)): + case is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value)): return $this->convertObjectParameterToScalarValue($value); default: diff --git a/lib/Doctrine/ORM/Id/AssignedGenerator.php b/lib/Doctrine/ORM/Id/AssignedGenerator.php index c9f9adad8..c306a8b0a 100644 --- a/lib/Doctrine/ORM/Id/AssignedGenerator.php +++ b/lib/Doctrine/ORM/Id/AssignedGenerator.php @@ -22,6 +22,7 @@ namespace Doctrine\ORM\Id; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\ORMException; +use Doctrine\Common\Util\ClassUtils; /** * Special generator for application-assigned identifiers (doesnt really generate anything). @@ -43,7 +44,7 @@ class AssignedGenerator extends AbstractIdGenerator */ public function generate(EntityManager $em, $entity) { - $class = $em->getClassMetadata(get_class($entity)); + $class = $em->getClassMetadata(ClassUtils::getClass($entity)); $idFields = $class->getIdentifierFieldNames(); $identifier = array(); diff --git a/lib/Doctrine/ORM/PersistentCollection.php b/lib/Doctrine/ORM/PersistentCollection.php index 25ccddd1a..2ad4abd5c 100644 --- a/lib/Doctrine/ORM/PersistentCollection.php +++ b/lib/Doctrine/ORM/PersistentCollection.php @@ -22,7 +22,8 @@ namespace Doctrine\ORM; use Doctrine\ORM\Mapping\ClassMetadata, Doctrine\Common\Collections\Collection, Doctrine\Common\Collections\ArrayCollection, - Closure; + Closure, + Doctrine\Common\Util\ClassUtils; /** * A PersistentCollection represents a collection of elements that have persistent state. @@ -306,7 +307,7 @@ final class PersistentCollection implements Collection $this->association['isOwningSide'] && $this->association['type'] === ClassMetadata::MANY_TO_MANY && $this->owner && - $this->em->getClassMetadata(get_class($this->owner))->isChangeTrackingNotify()) { + $this->em->getClassMetadata(ClassUtils::getClass($this->owner))->isChangeTrackingNotify()) { $this->em->getUnitOfWork()->scheduleForDirtyCheck($this->owner); } } diff --git a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php index d2638bea5..5459207b1 100644 --- a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php @@ -32,7 +32,8 @@ use PDO, Doctrine\ORM\Mapping\MappingException, Doctrine\ORM\Mapping\ClassMetadata, Doctrine\ORM\Events, - Doctrine\ORM\Event\LifecycleEventArgs; + Doctrine\ORM\Event\LifecycleEventArgs, + Doctrine\Common\Util\ClassUtils; /** * A BasicEntityPersiter maps an entity to a single table in a relational database. @@ -1499,11 +1500,11 @@ class BasicEntityPersister */ private function getIndividualValue($value) { - if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value))) { + if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) { if ($this->_em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE_MANAGED) { $idValues = $this->_em->getUnitOfWork()->getEntityIdentifier($value); } else { - $class = $this->_em->getClassMetadata(get_class($value)); + $class = $this->_em->getClassMetadata(ClassUtils::getClass($value)); $idValues = $class->getIdentifierValues($value); } diff --git a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php index c7dc08dff..eec5e3a21 100644 --- a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php +++ b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php @@ -23,7 +23,8 @@ namespace Doctrine\ORM\Persisters; use Doctrine\ORM\Mapping\ClassMetadata, Doctrine\ORM\PersistentCollection, - Doctrine\ORM\UnitOfWork; + Doctrine\ORM\UnitOfWork, + Doctrine\Common\Util\ClassUtils; /** * Persister for many-to-many collections. @@ -43,7 +44,7 @@ class ManyToManyPersister extends AbstractCollectionPersister protected function _getDeleteRowSQL(PersistentCollection $coll) { $mapping = $coll->getMapping(); - $class = $this->_em->getClassMetadata(get_class($coll->getOwner())); + $class = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner())); return 'DELETE FROM ' . $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform()) . ' WHERE ' . implode(' = ? AND ', $mapping['joinTableColumns']) . ' = ?'; @@ -80,7 +81,7 @@ class ManyToManyPersister extends AbstractCollectionPersister { $mapping = $coll->getMapping(); $columns = $mapping['joinTableColumns']; - $class = $this->_em->getClassMetadata(get_class($coll->getOwner())); + $class = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner())); $joinTable = $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform()); @@ -118,7 +119,7 @@ class ManyToManyPersister extends AbstractCollectionPersister $identifier2 = $this->_uow->getEntityIdentifier($element); if ($isComposite) { - $class1 = $this->_em->getClassMetadata(get_class($coll->getOwner())); + $class1 = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner())); $class2 = $coll->getTypeClass(); } @@ -150,7 +151,7 @@ class ManyToManyPersister extends AbstractCollectionPersister */ protected function _getDeleteSQL(PersistentCollection $coll) { - $class = $this->_em->getClassMetadata(get_class($coll->getOwner())); + $class = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner())); $mapping = $coll->getMapping(); return 'DELETE FROM ' . $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform()) @@ -178,7 +179,7 @@ class ManyToManyPersister extends AbstractCollectionPersister } // Composite identifier - $sourceClass = $this->_em->getClassMetadata(get_class($mapping->getOwner())); + $sourceClass = $this->_em->getClassMetadata(ClassUtils::getClass($mapping->getOwner())); foreach ($mapping['relationToSourceKeyColumns'] as $srcColumn) { $params[] = $identifier[$sourceClass->fieldNames[$srcColumn]]; diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 410f3b2c6..97a708563 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -27,7 +27,8 @@ use Exception, InvalidArgumentException, UnexpectedValueException, Doctrine\Common\Persistence\ObjectManagerAware, Doctrine\ORM\Event\LifecycleEventArgs, Doctrine\ORM\Mapping\ClassMetadata, - Doctrine\ORM\Proxy\Proxy; + Doctrine\ORM\Proxy\Proxy, + Doctrine\Common\Util\ClassUtils; /** * The UnitOfWork is responsible for tracking changes to objects during an @@ -375,7 +376,7 @@ class UnitOfWork implements PropertyChangedListener private function computeScheduleInsertsChangeSets() { foreach ($this->entityInsertions as $entity) { - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $this->computeChangeSet($class, $entity); } @@ -398,7 +399,7 @@ class UnitOfWork implements PropertyChangedListener throw new \InvalidArgumentException("Entity has to be managed for single computation " . self::objToStr($entity)); } - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); if ($class->isChangeTrackingDeferredImplicit()) { $this->persist($entity); @@ -433,7 +434,7 @@ class UnitOfWork implements PropertyChangedListener list ($entity, $changeset) = $update; $this->entityChangeSets[$oid] = $changeset; - $this->getEntityPersister(get_class($entity))->update($entity); + $this->getEntityPersister(ClassUtils::getClass($entity))->update($entity); } } @@ -838,7 +839,7 @@ class UnitOfWork implements PropertyChangedListener } if ( ! $class->isInheritanceTypeNone()) { - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); } $actualData = array(); @@ -886,7 +887,7 @@ class UnitOfWork implements PropertyChangedListener $hasListeners = $this->evm->hasListeners(Events::postPersist); foreach ($this->entityInsertions as $oid => $entity) { - if (get_class($entity) !== $className) { + if (ClassUtils::getClass($entity) !== $className) { continue; } @@ -945,7 +946,7 @@ class UnitOfWork implements PropertyChangedListener $hasPostUpdateListeners = $this->evm->hasListeners(Events::postUpdate); foreach ($this->entityUpdates as $oid => $entity) { - if ( ! (get_class($entity) === $className || $entity instanceof Proxy && get_parent_class($entity) === $className)) { + if (ClassUtils::getClass($entity) !== $className) { continue; } @@ -992,7 +993,7 @@ class UnitOfWork implements PropertyChangedListener $hasListeners = $this->evm->hasListeners(Events::postRemove); foreach ($this->entityDeletions as $oid => $entity) { - if ( ! (get_class($entity) == $className || $entity instanceof Proxy && get_parent_class($entity) == $className)) { + if (ClassUtils::getClass($entity) !== $className) { continue; } @@ -1043,7 +1044,7 @@ class UnitOfWork implements PropertyChangedListener $newNodes = array(); foreach ($entityChangeSet as $entity) { - $className = get_class($entity); + $className = ClassUtils::getClass($entity); if ($calc->hasClass($className)) { continue; @@ -1206,7 +1207,7 @@ class UnitOfWork implements PropertyChangedListener */ public function isScheduledForDirtyCheck($entity) { - $rootEntityName = $this->em->getClassMetadata(get_class($entity))->rootEntityName; + $rootEntityName = $this->em->getClassMetadata(ClassUtils::getClass($entity))->rootEntityName; return isset($this->scheduledForDirtyCheck[$rootEntityName][spl_object_hash($entity)]); } @@ -1287,7 +1288,7 @@ class UnitOfWork implements PropertyChangedListener */ public function addToIdentityMap($entity) { - $classMetadata = $this->em->getClassMetadata(get_class($entity)); + $classMetadata = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $idHash = implode(' ', $this->entityIdentifiers[spl_object_hash($entity)]); if ($idHash === '') { @@ -1335,7 +1336,7 @@ class UnitOfWork implements PropertyChangedListener // Note that you can not remember the NEW or DETACHED state in _entityStates since // the UoW does not hold references to such objects and the object hash can be reused. // More generally because the state may "change" between NEW/DETACHED without the UoW being aware of it. - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $id = $class->getIdentifierValues($entity); if ( ! $id) { @@ -1357,7 +1358,7 @@ class UnitOfWork implements PropertyChangedListener } // db lookup - if ($this->getEntityPersister(get_class($entity))->exists($entity)) { + if ($this->getEntityPersister($class->name)->exists($entity)) { return self::STATE_DETACHED; } @@ -1374,7 +1375,7 @@ class UnitOfWork implements PropertyChangedListener } // db lookup - if ($this->getEntityPersister(get_class($entity))->exists($entity)) { + if ($this->getEntityPersister($class->name)->exists($entity)) { return self::STATE_DETACHED; } @@ -1465,7 +1466,7 @@ class UnitOfWork implements PropertyChangedListener return false; } - $classMetadata = $this->em->getClassMetadata(get_class($entity)); + $classMetadata = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $idHash = implode(' ', $this->entityIdentifiers[$oid]); if ($idHash === '') { @@ -1520,7 +1521,7 @@ class UnitOfWork implements PropertyChangedListener $visited[$oid] = $entity; // Mark visited - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); // We assume NEW, so DETACHED entities result in an exception on flush (constraint violation). // If we would detect DETACHED here we would throw an exception anyway with the same @@ -1594,7 +1595,7 @@ class UnitOfWork implements PropertyChangedListener // can cause problems when a lazy proxy has to be initialized for the cascade operation. $this->cascadeRemove($entity, $visited); - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $entityState = $this->getEntityState($entity); switch ($entityState) { @@ -1660,7 +1661,7 @@ class UnitOfWork implements PropertyChangedListener $visited[$oid] = $entity; // mark visited - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); // First we assume DETACHED, although it can still be NEW but we can avoid // an extra db-roundtrip this way. If it is not MANAGED but has an identity, @@ -1814,7 +1815,7 @@ class UnitOfWork implements PropertyChangedListener if ($prevManagedCopy !== null) { $assocField = $assoc['fieldName']; - $prevClass = $this->em->getClassMetadata(get_class($prevManagedCopy)); + $prevClass = $this->em->getClassMetadata(ClassUtils::getClass($prevManagedCopy)); if ($assoc['type'] & ClassMetadata::TO_ONE) { $prevClass->reflFields[$assocField]->setValue($prevManagedCopy, $managedCopy); @@ -1921,7 +1922,7 @@ class UnitOfWork implements PropertyChangedListener $visited[$oid] = $entity; // mark visited - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); if ($this->getEntityState($entity) !== self::STATE_MANAGED) { throw ORMInvalidArgumentException::entityNotManaged($entity); @@ -1943,7 +1944,7 @@ class UnitOfWork implements PropertyChangedListener */ private function cascadeRefresh($entity, array &$visited) { - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $associationMappings = array_filter( $class->associationMappings, @@ -1984,7 +1985,7 @@ class UnitOfWork implements PropertyChangedListener */ private function cascadeDetach($entity, array &$visited) { - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $associationMappings = array_filter( $class->associationMappings, @@ -2026,7 +2027,7 @@ class UnitOfWork implements PropertyChangedListener */ private function cascadeMerge($entity, $managedCopy, array &$visited) { - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $associationMappings = array_filter( $class->associationMappings, @@ -2064,7 +2065,7 @@ class UnitOfWork implements PropertyChangedListener */ private function cascadePersist($entity, array &$visited) { - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $associationMappings = array_filter( $class->associationMappings, @@ -2105,7 +2106,7 @@ class UnitOfWork implements PropertyChangedListener */ private function cascadeRemove($entity, array &$visited) { - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $associationMappings = array_filter( $class->associationMappings, @@ -2151,13 +2152,12 @@ class UnitOfWork implements PropertyChangedListener throw ORMInvalidArgumentException::entityNotManaged($entity); } - $entityName = get_class($entity); - $class = $this->em->getClassMetadata($entityName); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); switch ($lockMode) { case \Doctrine\DBAL\LockMode::OPTIMISTIC; if ( ! $class->isVersioned) { - throw OptimisticLockException::notVersioned($entityName); + throw OptimisticLockException::notVersioned($class->name); } if ($lockVersion === null) { @@ -2689,7 +2689,7 @@ class UnitOfWork implements PropertyChangedListener */ public function scheduleForDirtyCheck($entity) { - $rootClassName = $this->em->getClassMetadata(get_class($entity))->rootEntityName; + $rootClassName = $this->em->getClassMetadata(ClassUtils::getClass($entity))->rootEntityName; $this->scheduledForDirtyCheck[$rootClassName][spl_object_hash($entity)] = $entity; } @@ -2827,7 +2827,7 @@ class UnitOfWork implements PropertyChangedListener public function propertyChanged($entity, $propertyName, $oldValue, $newValue) { $oid = spl_object_hash($entity); - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $isAssocField = isset($class->associationMappings[$propertyName]); From c4a2eaea49dcf9dd654e90364362959882b904fa Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 31 Mar 2012 01:37:27 +0200 Subject: [PATCH 2/6] Adding additional missing calls to classutils instead of get_class --- lib/Doctrine/ORM/UnitOfWork.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 97a708563..fff20ff1a 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -493,7 +493,7 @@ class UnitOfWork implements PropertyChangedListener } if ( ! $class->isInheritanceTypeNone()) { - $class = $this->em->getClassMetadata(get_class($entity)); + $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); } // Fire PreFlush lifecycle callbacks @@ -1398,7 +1398,7 @@ class UnitOfWork implements PropertyChangedListener public function removeFromIdentityMap($entity) { $oid = spl_object_hash($entity); - $classMetadata = $this->em->getClassMetadata(get_class($entity)); + $classMetadata = $this->em->getClassMetadata(ClassUtils::getClass($entity)); $idHash = implode(' ', $this->entityIdentifiers[$oid]); if ($idHash === '') { From 37279d075311ffd2783e3f11d141df9cccd7d206 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 31 Mar 2012 02:18:52 +0200 Subject: [PATCH 3/6] Adding test to verify validity of changes (fails without them) --- .../Functional/ProxiesLikeEntitiesTest.php | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 tests/Doctrine/Tests/ORM/Functional/ProxiesLikeEntitiesTest.php diff --git a/tests/Doctrine/Tests/ORM/Functional/ProxiesLikeEntitiesTest.php b/tests/Doctrine/Tests/ORM/Functional/ProxiesLikeEntitiesTest.php new file mode 100644 index 000000000..66184a8a8 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/ProxiesLikeEntitiesTest.php @@ -0,0 +1,103 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'), + )); + } catch (\Exception $e) { + } + $this->user = new CmsUser(); + $this->user->username = 'ocramius'; + $this->user->name = 'Marco'; + $this->_em->persist($this->user); + $this->_em->flush(); + $this->_em->clear(); + } + + /** + * Verifies that a proxy can be successfully persisted and updated + */ + public function testPersistUpdate() + { + // Considering case (a) + $persister = $this->_em->getUnitOfWork()->getEntityPersister('Doctrine\Tests\Models\CMS\CmsUser'); + $proxy = new Proxy($persister, array()); + $proxy->__isInitialized__ = true; + $proxy->username = 'ocra'; + $proxy->name = 'Marco'; + $this->_em->persist($proxy); + $this->_em->flush(); + $this->assertNotNull($proxy->getId()); + $proxy->name = 'Marco Pivetta'; + $this + ->_em + ->getUnitOfWork() + ->computeChangeSet($this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'), $proxy); + $this->assertNotEmpty($this->_em->getUnitOfWork()->getEntityChangeSet($proxy)); + $this->assertEquals('Marco Pivetta', $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $proxy->getId())->name); + $this->_em->remove($proxy); + $this->_em->flush(); + } + + public function testEntityWithIdentifier() + { + // Considering case (b) + $persister = $this->_em->getUnitOfWork()->getEntityPersister('Doctrine\Tests\Models\CMS\CmsUser'); + $uninitializedProxy = new Proxy($persister, array('id' => $this->user->getId())); + $uninitializedProxy->id = $this->user->getId(); + $uninitializedProxy->username = 'ocra'; + $uninitializedProxy->name = 'Marco Pivetta'; + $this->_em->persist($uninitializedProxy); + $this->_em->flush(); + $this->assertEquals($this->user->getId(), $uninitializedProxy->getId()); + $this->_em->remove($uninitializedProxy); + $this->_em->flush(); + } + + /** + * Verifying that proxies can be used without problems as query parameters + */ + public function testProxyAsDqlParameterPersist() + { + $persister = $this->_em->getUnitOfWork()->getEntityPersister('Doctrine\Tests\Models\CMS\CmsUser'); + $proxy = new Proxy($persister, array('id' => $this->user->getId())); + $proxy->id = $this->user->getId(); + $result = $this + ->_em + ->createQuery('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u = ?1') + ->setParameter(1, $proxy) + ->getSingleResult(); + $this->assertSame($this->user->getId(), $result->getId()); + $this->_em->remove($proxy); + $this->_em->flush(); + } + + protected function tearDown() + { + $this->_em->createQuery('DELETE FROM Doctrine\Tests\Models\CMS\CmsUser u')->execute(); + } +} \ No newline at end of file From d1e868a32ae8e61d8cfd70afb0d5750ada489a0e Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 31 Mar 2012 23:26:33 +0200 Subject: [PATCH 4/6] Removing registration of proxy ClassMetadata by the proxyFactory Ensuring that functionality is kept by checking for the real class name in the ClassMetadataFactory --- lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php | 3 +++ lib/Doctrine/ORM/Proxy/ProxyFactory.php | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php index 2aaa30a44..f6e8a52e3 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php @@ -24,6 +24,7 @@ use ReflectionException, Doctrine\ORM\EntityManager, Doctrine\DBAL\Platforms, Doctrine\ORM\Events, + Doctrine\Common\Util\ClassUtils, Doctrine\Common\Persistence\Mapping\RuntimeReflectionService, Doctrine\Common\Persistence\Mapping\ReflectionService, Doctrine\Common\Persistence\Mapping\ClassMetadataFactory as ClassMetadataFactoryInterface; @@ -168,6 +169,8 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface return $this->loadedMetadata[$realClassName]; } + } else { + $realClassName = ClassUtils::getRealClass($realClassName); } if ($this->cacheDriver) { diff --git a/lib/Doctrine/ORM/Proxy/ProxyFactory.php b/lib/Doctrine/ORM/Proxy/ProxyFactory.php index 21d033e7e..df10798e1 100644 --- a/lib/Doctrine/ORM/Proxy/ProxyFactory.php +++ b/lib/Doctrine/ORM/Proxy/ProxyFactory.php @@ -93,10 +93,6 @@ class ProxyFactory require $fileName; } - if ( ! $this->_em->getMetadataFactory()->hasMetadataFor($fqn)) { - $this->_em->getMetadataFactory()->setMetadataFor($fqn, $this->_em->getClassMetadata($className)); - } - $entityPersister = $this->_em->getUnitOfWork()->getEntityPersister($className); return new $fqn($entityPersister, $identifier); From 85ea27dba2d7531531e5adeb51463e1d489ac6c8 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 1 Apr 2012 15:55:49 +0200 Subject: [PATCH 5/6] Adding tests for additional usages of the proxy classname in ORM public API Like Proxy classnames in DQL, EM#getRepository, EM#getReference --- .../Functional/ProxiesLikeEntitiesTest.php | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/Doctrine/Tests/ORM/Functional/ProxiesLikeEntitiesTest.php b/tests/Doctrine/Tests/ORM/Functional/ProxiesLikeEntitiesTest.php index 66184a8a8..52ac8f591 100644 --- a/tests/Doctrine/Tests/ORM/Functional/ProxiesLikeEntitiesTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/ProxiesLikeEntitiesTest.php @@ -96,6 +96,36 @@ class ProxiesLikeEntitiesTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->flush(); } + /** + * Verifying that proxies can be used without problems as query parameters + */ + public function testFindWithProxyName() + { + $result = $this + ->_em + ->find('Doctrine\Tests\Proxies\__CG__\Doctrine\Tests\Models\CMS\CmsUser', $this->user->getId()); + $this->assertSame($this->user->getId(), $result->getId()); + $this->_em->clear(); + $result = $this + ->_em + ->getReference('Doctrine\Tests\Proxies\__CG__\Doctrine\Tests\Models\CMS\CmsUser', $this->user->getId()); + $this->assertSame($this->user->getId(), $result->getId()); + $this->_em->clear(); + $result = $this + ->_em + ->getRepository('Doctrine\Tests\Proxies\__CG__\Doctrine\Tests\Models\CMS\CmsUser') + ->findOneBy(array('username' => $this->user->username)); + $this->assertSame($this->user->getId(), $result->getId()); + $this->_em->clear(); + $result = $this + ->_em + ->createQuery('SELECT u FROM Doctrine\Tests\Proxies\__CG__\Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1') + ->setParameter(1, $this->user->getId()) + ->getSingleResult(); + $this->assertSame($this->user->getId(), $result->getId()); + $this->_em->clear(); + } + protected function tearDown() { $this->_em->createQuery('DELETE FROM Doctrine\Tests\Models\CMS\CmsUser u')->execute(); From cb7a77cc038b986adb15ee561a8c2c5661499490 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sun, 1 Apr 2012 16:27:31 +0200 Subject: [PATCH 6/6] Removing usage of ClassUtil where not strictly needed Optimizing the ClassMetadataFactory API instead and using ClassMetadata to check actual class names as da962f2e and c27b4de0 introduced too much overhead --- lib/Doctrine/ORM/Id/AssignedGenerator.php | 3 +- .../ORM/Mapping/ClassMetadataFactory.php | 61 ++++++++++--------- lib/Doctrine/ORM/PersistentCollection.php | 5 +- .../ORM/Persisters/BasicEntityPersister.php | 2 +- .../ORM/Persisters/ManyToManyPersister.php | 13 ++-- lib/Doctrine/ORM/UnitOfWork.php | 57 +++++++++-------- 6 files changed, 69 insertions(+), 72 deletions(-) diff --git a/lib/Doctrine/ORM/Id/AssignedGenerator.php b/lib/Doctrine/ORM/Id/AssignedGenerator.php index c306a8b0a..c9f9adad8 100644 --- a/lib/Doctrine/ORM/Id/AssignedGenerator.php +++ b/lib/Doctrine/ORM/Id/AssignedGenerator.php @@ -22,7 +22,6 @@ namespace Doctrine\ORM\Id; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\ORMException; -use Doctrine\Common\Util\ClassUtils; /** * Special generator for application-assigned identifiers (doesnt really generate anything). @@ -44,7 +43,7 @@ class AssignedGenerator extends AbstractIdGenerator */ public function generate(EntityManager $em, $entity) { - $class = $em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $em->getClassMetadata(get_class($entity)); $idFields = $class->getIdentifierFieldNames(); $identifier = array(); diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php index f6e8a52e3..bf7d5d5c1 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php @@ -155,43 +155,44 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface */ public function getMetadataFor($className) { - if ( ! isset($this->loadedMetadata[$className])) { - $realClassName = $className; + if (isset($this->loadedMetadata[$className])) { + return $this->loadedMetadata[$className]; + } - // Check for namespace alias - if (strpos($className, ':') !== false) { - list($namespaceAlias, $simpleClassName) = explode(':', $className); - $realClassName = $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName; + $realClassName = $className; - if (isset($this->loadedMetadata[$realClassName])) { - // We do not have the alias name in the map, include it - $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; + // Check for namespace alias + if (strpos($className, ':') !== false) { + list($namespaceAlias, $simpleClassName) = explode(':', $className); + $realClassName = $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName; + } else { + $realClassName = ClassUtils::getRealClass($realClassName); + } - return $this->loadedMetadata[$realClassName]; - } + if (isset($this->loadedMetadata[$realClassName])) { + // We do not have the alias name in the map, include it + $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; + return $this->loadedMetadata[$realClassName]; + } + + if ($this->cacheDriver) { + if (($cached = $this->cacheDriver->fetch("$realClassName\$CLASSMETADATA")) !== false) { + $this->wakeupReflection($cached, $this->getReflectionService()); + $this->loadedMetadata[$realClassName] = $cached; } else { - $realClassName = ClassUtils::getRealClass($realClassName); - } - - if ($this->cacheDriver) { - if (($cached = $this->cacheDriver->fetch("$realClassName\$CLASSMETADATA")) !== false) { - $this->wakeupReflection($cached, $this->getReflectionService()); - $this->loadedMetadata[$realClassName] = $cached; - } else { - foreach ($this->loadMetadata($realClassName) as $loadedClassName) { - $this->cacheDriver->save( - "$loadedClassName\$CLASSMETADATA", $this->loadedMetadata[$loadedClassName], null - ); - } + foreach ($this->loadMetadata($realClassName) as $loadedClassName) { + $this->cacheDriver->save( + "$loadedClassName\$CLASSMETADATA", $this->loadedMetadata[$loadedClassName], null + ); } - } else { - $this->loadMetadata($realClassName); } + } else { + $this->loadMetadata($realClassName); + } - if ($className != $realClassName) { - // We do not have the alias name in the map, include it - $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; - } + if ($className != $realClassName) { + // We do not have the alias name in the map, include it + $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; } return $this->loadedMetadata[$className]; diff --git a/lib/Doctrine/ORM/PersistentCollection.php b/lib/Doctrine/ORM/PersistentCollection.php index 2ad4abd5c..25ccddd1a 100644 --- a/lib/Doctrine/ORM/PersistentCollection.php +++ b/lib/Doctrine/ORM/PersistentCollection.php @@ -22,8 +22,7 @@ namespace Doctrine\ORM; use Doctrine\ORM\Mapping\ClassMetadata, Doctrine\Common\Collections\Collection, Doctrine\Common\Collections\ArrayCollection, - Closure, - Doctrine\Common\Util\ClassUtils; + Closure; /** * A PersistentCollection represents a collection of elements that have persistent state. @@ -307,7 +306,7 @@ final class PersistentCollection implements Collection $this->association['isOwningSide'] && $this->association['type'] === ClassMetadata::MANY_TO_MANY && $this->owner && - $this->em->getClassMetadata(ClassUtils::getClass($this->owner))->isChangeTrackingNotify()) { + $this->em->getClassMetadata(get_class($this->owner))->isChangeTrackingNotify()) { $this->em->getUnitOfWork()->scheduleForDirtyCheck($this->owner); } } diff --git a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php index 5459207b1..48508981d 100644 --- a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php @@ -1504,7 +1504,7 @@ class BasicEntityPersister if ($this->_em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE_MANAGED) { $idValues = $this->_em->getUnitOfWork()->getEntityIdentifier($value); } else { - $class = $this->_em->getClassMetadata(ClassUtils::getClass($value)); + $class = $this->_em->getClassMetadata(get_class($value)); $idValues = $class->getIdentifierValues($value); } diff --git a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php index eec5e3a21..c7dc08dff 100644 --- a/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php +++ b/lib/Doctrine/ORM/Persisters/ManyToManyPersister.php @@ -23,8 +23,7 @@ namespace Doctrine\ORM\Persisters; use Doctrine\ORM\Mapping\ClassMetadata, Doctrine\ORM\PersistentCollection, - Doctrine\ORM\UnitOfWork, - Doctrine\Common\Util\ClassUtils; + Doctrine\ORM\UnitOfWork; /** * Persister for many-to-many collections. @@ -44,7 +43,7 @@ class ManyToManyPersister extends AbstractCollectionPersister protected function _getDeleteRowSQL(PersistentCollection $coll) { $mapping = $coll->getMapping(); - $class = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner())); + $class = $this->_em->getClassMetadata(get_class($coll->getOwner())); return 'DELETE FROM ' . $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform()) . ' WHERE ' . implode(' = ? AND ', $mapping['joinTableColumns']) . ' = ?'; @@ -81,7 +80,7 @@ class ManyToManyPersister extends AbstractCollectionPersister { $mapping = $coll->getMapping(); $columns = $mapping['joinTableColumns']; - $class = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner())); + $class = $this->_em->getClassMetadata(get_class($coll->getOwner())); $joinTable = $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform()); @@ -119,7 +118,7 @@ class ManyToManyPersister extends AbstractCollectionPersister $identifier2 = $this->_uow->getEntityIdentifier($element); if ($isComposite) { - $class1 = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner())); + $class1 = $this->_em->getClassMetadata(get_class($coll->getOwner())); $class2 = $coll->getTypeClass(); } @@ -151,7 +150,7 @@ class ManyToManyPersister extends AbstractCollectionPersister */ protected function _getDeleteSQL(PersistentCollection $coll) { - $class = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner())); + $class = $this->_em->getClassMetadata(get_class($coll->getOwner())); $mapping = $coll->getMapping(); return 'DELETE FROM ' . $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform()) @@ -179,7 +178,7 @@ class ManyToManyPersister extends AbstractCollectionPersister } // Composite identifier - $sourceClass = $this->_em->getClassMetadata(ClassUtils::getClass($mapping->getOwner())); + $sourceClass = $this->_em->getClassMetadata(get_class($mapping->getOwner())); foreach ($mapping['relationToSourceKeyColumns'] as $srcColumn) { $params[] = $identifier[$sourceClass->fieldNames[$srcColumn]]; diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index fff20ff1a..c1244934b 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -27,8 +27,7 @@ use Exception, InvalidArgumentException, UnexpectedValueException, Doctrine\Common\Persistence\ObjectManagerAware, Doctrine\ORM\Event\LifecycleEventArgs, Doctrine\ORM\Mapping\ClassMetadata, - Doctrine\ORM\Proxy\Proxy, - Doctrine\Common\Util\ClassUtils; + Doctrine\ORM\Proxy\Proxy; /** * The UnitOfWork is responsible for tracking changes to objects during an @@ -376,7 +375,7 @@ class UnitOfWork implements PropertyChangedListener private function computeScheduleInsertsChangeSets() { foreach ($this->entityInsertions as $entity) { - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); $this->computeChangeSet($class, $entity); } @@ -399,7 +398,7 @@ class UnitOfWork implements PropertyChangedListener throw new \InvalidArgumentException("Entity has to be managed for single computation " . self::objToStr($entity)); } - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); if ($class->isChangeTrackingDeferredImplicit()) { $this->persist($entity); @@ -434,7 +433,7 @@ class UnitOfWork implements PropertyChangedListener list ($entity, $changeset) = $update; $this->entityChangeSets[$oid] = $changeset; - $this->getEntityPersister(ClassUtils::getClass($entity))->update($entity); + $this->getEntityPersister(get_class($entity))->update($entity); } } @@ -493,7 +492,7 @@ class UnitOfWork implements PropertyChangedListener } if ( ! $class->isInheritanceTypeNone()) { - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); } // Fire PreFlush lifecycle callbacks @@ -839,7 +838,7 @@ class UnitOfWork implements PropertyChangedListener } if ( ! $class->isInheritanceTypeNone()) { - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); } $actualData = array(); @@ -887,7 +886,7 @@ class UnitOfWork implements PropertyChangedListener $hasListeners = $this->evm->hasListeners(Events::postPersist); foreach ($this->entityInsertions as $oid => $entity) { - if (ClassUtils::getClass($entity) !== $className) { + if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { continue; } @@ -946,7 +945,7 @@ class UnitOfWork implements PropertyChangedListener $hasPostUpdateListeners = $this->evm->hasListeners(Events::postUpdate); foreach ($this->entityUpdates as $oid => $entity) { - if (ClassUtils::getClass($entity) !== $className) { + if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { continue; } @@ -993,7 +992,7 @@ class UnitOfWork implements PropertyChangedListener $hasListeners = $this->evm->hasListeners(Events::postRemove); foreach ($this->entityDeletions as $oid => $entity) { - if (ClassUtils::getClass($entity) !== $className) { + if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { continue; } @@ -1044,7 +1043,7 @@ class UnitOfWork implements PropertyChangedListener $newNodes = array(); foreach ($entityChangeSet as $entity) { - $className = ClassUtils::getClass($entity); + $className = $this->em->getClassMetadata(get_class($entity))->name; if ($calc->hasClass($className)) { continue; @@ -1207,7 +1206,7 @@ class UnitOfWork implements PropertyChangedListener */ public function isScheduledForDirtyCheck($entity) { - $rootEntityName = $this->em->getClassMetadata(ClassUtils::getClass($entity))->rootEntityName; + $rootEntityName = $this->em->getClassMetadata(get_class($entity))->rootEntityName; return isset($this->scheduledForDirtyCheck[$rootEntityName][spl_object_hash($entity)]); } @@ -1288,7 +1287,7 @@ class UnitOfWork implements PropertyChangedListener */ public function addToIdentityMap($entity) { - $classMetadata = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $classMetadata = $this->em->getClassMetadata(get_class($entity)); $idHash = implode(' ', $this->entityIdentifiers[spl_object_hash($entity)]); if ($idHash === '') { @@ -1336,7 +1335,7 @@ class UnitOfWork implements PropertyChangedListener // Note that you can not remember the NEW or DETACHED state in _entityStates since // the UoW does not hold references to such objects and the object hash can be reused. // More generally because the state may "change" between NEW/DETACHED without the UoW being aware of it. - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); $id = $class->getIdentifierValues($entity); if ( ! $id) { @@ -1398,7 +1397,7 @@ class UnitOfWork implements PropertyChangedListener public function removeFromIdentityMap($entity) { $oid = spl_object_hash($entity); - $classMetadata = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $classMetadata = $this->em->getClassMetadata(get_class($entity)); $idHash = implode(' ', $this->entityIdentifiers[$oid]); if ($idHash === '') { @@ -1466,7 +1465,7 @@ class UnitOfWork implements PropertyChangedListener return false; } - $classMetadata = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $classMetadata = $this->em->getClassMetadata(get_class($entity)); $idHash = implode(' ', $this->entityIdentifiers[$oid]); if ($idHash === '') { @@ -1521,7 +1520,7 @@ class UnitOfWork implements PropertyChangedListener $visited[$oid] = $entity; // Mark visited - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); // We assume NEW, so DETACHED entities result in an exception on flush (constraint violation). // If we would detect DETACHED here we would throw an exception anyway with the same @@ -1595,7 +1594,7 @@ class UnitOfWork implements PropertyChangedListener // can cause problems when a lazy proxy has to be initialized for the cascade operation. $this->cascadeRemove($entity, $visited); - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); $entityState = $this->getEntityState($entity); switch ($entityState) { @@ -1661,7 +1660,7 @@ class UnitOfWork implements PropertyChangedListener $visited[$oid] = $entity; // mark visited - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); // First we assume DETACHED, although it can still be NEW but we can avoid // an extra db-roundtrip this way. If it is not MANAGED but has an identity, @@ -1815,7 +1814,7 @@ class UnitOfWork implements PropertyChangedListener if ($prevManagedCopy !== null) { $assocField = $assoc['fieldName']; - $prevClass = $this->em->getClassMetadata(ClassUtils::getClass($prevManagedCopy)); + $prevClass = $this->em->getClassMetadata(get_class($prevManagedCopy)); if ($assoc['type'] & ClassMetadata::TO_ONE) { $prevClass->reflFields[$assocField]->setValue($prevManagedCopy, $managedCopy); @@ -1922,7 +1921,7 @@ class UnitOfWork implements PropertyChangedListener $visited[$oid] = $entity; // mark visited - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); if ($this->getEntityState($entity) !== self::STATE_MANAGED) { throw ORMInvalidArgumentException::entityNotManaged($entity); @@ -1944,7 +1943,7 @@ class UnitOfWork implements PropertyChangedListener */ private function cascadeRefresh($entity, array &$visited) { - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); $associationMappings = array_filter( $class->associationMappings, @@ -1985,7 +1984,7 @@ class UnitOfWork implements PropertyChangedListener */ private function cascadeDetach($entity, array &$visited) { - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); $associationMappings = array_filter( $class->associationMappings, @@ -2027,7 +2026,7 @@ class UnitOfWork implements PropertyChangedListener */ private function cascadeMerge($entity, $managedCopy, array &$visited) { - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); $associationMappings = array_filter( $class->associationMappings, @@ -2065,7 +2064,7 @@ class UnitOfWork implements PropertyChangedListener */ private function cascadePersist($entity, array &$visited) { - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); $associationMappings = array_filter( $class->associationMappings, @@ -2106,7 +2105,7 @@ class UnitOfWork implements PropertyChangedListener */ private function cascadeRemove($entity, array &$visited) { - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); $associationMappings = array_filter( $class->associationMappings, @@ -2152,7 +2151,7 @@ class UnitOfWork implements PropertyChangedListener throw ORMInvalidArgumentException::entityNotManaged($entity); } - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); switch ($lockMode) { case \Doctrine\DBAL\LockMode::OPTIMISTIC; @@ -2689,7 +2688,7 @@ class UnitOfWork implements PropertyChangedListener */ public function scheduleForDirtyCheck($entity) { - $rootClassName = $this->em->getClassMetadata(ClassUtils::getClass($entity))->rootEntityName; + $rootClassName = $this->em->getClassMetadata(get_class($entity))->rootEntityName; $this->scheduledForDirtyCheck[$rootClassName][spl_object_hash($entity)] = $entity; } @@ -2827,7 +2826,7 @@ class UnitOfWork implements PropertyChangedListener public function propertyChanged($entity, $propertyName, $oldValue, $newValue) { $oid = spl_object_hash($entity); - $class = $this->em->getClassMetadata(ClassUtils::getClass($entity)); + $class = $this->em->getClassMetadata(get_class($entity)); $isAssocField = isset($class->associationMappings[$propertyName]);