diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php index 878c130c2..1453aab3e 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php @@ -234,20 +234,7 @@ class ObjectHydrator extends AbstractHydrator $this->_hints['fetchAlias'] = $dqlAlias; - $entity = $this->_uow->createEntity($className, $data, $this->_hints); - - //TODO: These should be invoked later, after hydration, because associations may not yet be loaded here. - if (isset($this->_ce[$className]->lifecycleCallbacks[Events::postLoad])) { - $this->_ce[$className]->invokeLifecycleCallbacks(Events::postLoad, $entity); - } - - $evm = $this->_em->getEventManager(); - - if ($evm->hasListeners(Events::postLoad)) { - $evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->_em)); - } - - return $entity; + return $this->_uow->createEntity($className, $data, $this->_hints); } private function _getEntityFromIdentityMap($className, array $data) diff --git a/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php index 648f64979..09c2c7f3d 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php @@ -130,17 +130,6 @@ class SimpleObjectHydrator extends AbstractHydrator $uow = $this->_em->getUnitOfWork(); $entity = $uow->createEntity($entityName, $data, $this->_hints); - //TODO: These should be invoked later, after hydration, because associations may not yet be loaded here. - if (isset($this->class->lifecycleCallbacks[Events::postLoad])) { - $this->class->invokeLifecycleCallbacks(Events::postLoad, $entity); - } - - $evm = $this->_em->getEventManager(); - - if ($evm->hasListeners(Events::postLoad)) { - $evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->_em)); - } - $result[] = $entity; } @@ -191,4 +180,4 @@ class SimpleObjectHydrator extends AbstractHydrator ); } } -} \ No newline at end of file +} diff --git a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php index 629c1fa2a..673d97496 100644 --- a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php @@ -698,16 +698,6 @@ class BasicEntityPersister $hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT); $hydrator->hydrateAll($stmt, $this->_rsm, array(Query::HINT_REFRESH => true)); - - if (isset($this->_class->lifecycleCallbacks[Events::postLoad])) { - $this->_class->invokeLifecycleCallbacks(Events::postLoad, $entity); - } - - $evm = $this->_em->getEventManager(); - - if ($evm->hasListeners(Events::postLoad)) { - $evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->_em)); - } } /** diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index fc892b138..2f555e6e1 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -2501,6 +2501,17 @@ class UnitOfWork implements PropertyChangedListener } } + if ($overrideLocalValues) { + if (isset($class->lifecycleCallbacks[Events::postLoad])) { + $class->invokeLifecycleCallbacks(Events::postLoad, $entity); + } + + + if ($this->evm->hasListeners(Events::postLoad)) { + $this->evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->em)); + } + } + return $entity; } diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1655Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1655Test.php new file mode 100644 index 000000000..22b20e722 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1655Test.php @@ -0,0 +1,144 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1655Foo'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1655Bar'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1655Baz'), + )); + } catch(\Exception $e) { + + } + } + + public function testPostLoadOneToManyInheritance() + { + $cm = $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1655Foo'); + $this->assertEquals(array("postLoad" => array("postLoad")), $cm->lifecycleCallbacks); + + $cm = $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC1655Bar'); + $this->assertEquals(array("postLoad" => array("postLoad", "postSubLoaded")), $cm->lifecycleCallbacks); + + $baz = new DDC1655Baz(); + $foo = new DDC1655Foo(); + $foo->baz = $baz; + $bar = new DDC1655Bar(); + $bar->baz = $baz; + + $this->_em->persist($foo); + $this->_em->persist($bar); + $this->_em->persist($baz); + $this->_em->flush(); + $this->_em->clear(); + + $baz = $this->_em->find(get_class($baz), $baz->id); + foreach ($baz->foos as $foo) { + $this->assertEquals(1, $foo->loaded, "should have loaded callback counter incremented for " . get_class($foo)); + } + } + + /** + * Check that post load is not executed several times when the entity + * is rehydrated again although its already known. + */ + public function testPostLoadInheritanceChild() + { + $bar = new DDC1655Bar(); + + $this->_em->persist($bar); + $this->_em->flush(); + $this->_em->clear(); + + $bar = $this->_em->find(get_class($bar), $bar->id); + $this->assertEquals(1, $bar->loaded); + $this->assertEquals(1, $bar->subLoaded); + + $bar = $this->_em->find(get_class($bar), $bar->id); + $this->assertEquals(1, $bar->loaded); + $this->assertEquals(1, $bar->subLoaded); + + $dql = "SELECT b FROM " . __NAMESPACE__ . "\DDC1655Bar b WHERE b.id = ?1"; + $bar = $this->_em->createQuery($dql)->setParameter(1, $bar->id)->getSingleResult(); + + $this->assertEquals(1, $bar->loaded); + $this->assertEquals(1, $bar->subLoaded); + + $this->_em->refresh($bar); + + $this->assertEquals(2, $bar->loaded); + $this->assertEquals(2, $bar->subLoaded); + } +} + +/** + * @Entity + * @InheritanceType("SINGLE_TABLE") + * @DiscriminatorMap({ + * "foo" = "DDC1655Foo", + * "bar" = "DDC1655Bar" + * }) + * @HasLifecycleCallbacks + */ +class DDC1655Foo +{ + /** @Id @GeneratedValue @Column(type="integer") */ + public $id; + + public $loaded = 0; + + /** + * @ManyToOne(targetEntity="DDC1655Baz", inversedBy="foos") + */ + public $baz; + + /** + * @PostLoad + */ + public function postLoad() + { + $this->loaded++; + } +} + +/** + * @Entity + * @HasLifecycleCallbacks + */ +class DDC1655Bar extends DDC1655Foo +{ + public $subLoaded; + + /** + * @PostLoad + */ + public function postSubLoaded() + { + $this->subLoaded++; + } +} + +/** + * @Entity + */ +class DDC1655Baz +{ + /** @Id @GeneratedValue @Column(type="integer") */ + public $id; + + /** + * @OneToMany(targetEntity="DDC1655Foo", mappedBy="baz") + */ + public $foos = array(); +}