From 151192ae3724334c033431084d4afa9190ebd4e1 Mon Sep 17 00:00:00 2001 From: Stefan Kleff Date: Thu, 10 Jan 2013 14:54:52 +0100 Subject: [PATCH 1/4] The EntityManager was not injected in uninitialized proxys which are ObjectManagerAware. I ran into that problem while I had two objects in the identitymap while hydrating a collection: one was new a "real" entity and the other one was an uninitialized proxy. For "real" entities the em is injected in line 2427, for new entities it is injected in 2436->2364, but for proxies this is missing. According to the comment "inject ObjectManager into just loaded proxies." the code in line 2427 should do this, but in fact it is just used if it is a "real" entity or an already initialized proxy. Moving the injection to outside of the condition in line 2411 (if the entity is an unitialized proxy) solves this. --- lib/Doctrine/ORM/UnitOfWork.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 24f05748d..6e7eeb129 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -2477,19 +2477,20 @@ class UnitOfWork implements PropertyChangedListener if ($entity instanceof NotifyPropertyChanged) { $entity->addPropertyChangedListener($this); } + } else { $overrideLocalValues = isset($hints[Query::HINT_REFRESH]); // If only a specific entity is set to refresh, check that it's the one if(isset($hints[Query::HINT_REFRESH_ENTITY])) { $overrideLocalValues = $hints[Query::HINT_REFRESH_ENTITY] === $entity; - - // inject ObjectManager into just loaded proxies. - if ($overrideLocalValues && $entity instanceof ObjectManagerAware) { - $entity->injectObjectManager($this->em, $class); - } } } + + // inject ObjectManager into just loaded proxies. + if ($overrideLocalValues && $entity instanceof ObjectManagerAware) { + $entity->injectObjectManager($this->em, $class); + } if ($overrideLocalValues) { $this->originalEntityData[$oid] = $data; From dc925cc9c5461ca4160c685cd40a4a769bc168eb Mon Sep 17 00:00:00 2001 From: Stefan Kleff Date: Thu, 10 Jan 2013 15:19:44 +0100 Subject: [PATCH 2/4] fixed indentation Restored old way of injection to just inject it during a refresh Added injection for initialized proxies --- lib/Doctrine/ORM/UnitOfWork.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 6e7eeb129..356ea02b2 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -2478,6 +2478,11 @@ class UnitOfWork implements PropertyChangedListener $entity->addPropertyChangedListener($this); } + // inject ObjectManager into just loaded proxies. + if ($overrideLocalValues && $entity instanceof ObjectManagerAware) { + $entity->injectObjectManager($this->em, $class); + } + } else { $overrideLocalValues = isset($hints[Query::HINT_REFRESH]); @@ -2485,12 +2490,12 @@ class UnitOfWork implements PropertyChangedListener if(isset($hints[Query::HINT_REFRESH_ENTITY])) { $overrideLocalValues = $hints[Query::HINT_REFRESH_ENTITY] === $entity; } + + // inject ObjectManager upon refresh. + if ($overrideLocalValues && $entity instanceof ObjectManagerAware) { + $entity->injectObjectManager($this->em, $class); + } } - - // inject ObjectManager into just loaded proxies. - if ($overrideLocalValues && $entity instanceof ObjectManagerAware) { - $entity->injectObjectManager($this->em, $class); - } if ($overrideLocalValues) { $this->originalEntityData[$oid] = $data; From 6032e3efd88e762d314ad8043e68eb42c50e3df6 Mon Sep 17 00:00:00 2001 From: Stefan Kleff Date: Thu, 10 Jan 2013 16:10:29 +0100 Subject: [PATCH 3/4] Added test --- .../ORM/Functional/Ticket/DDC2231Test.php | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2231Test.php diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2231Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2231Test.php new file mode 100644 index 000000000..822683437 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2231Test.php @@ -0,0 +1,103 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2231EntityX'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2231EntityY'), + )); + } + + public function testInjectObjectManagerInProxyIfInitializedInUow() + { + $_x = new DDC2231EntityX; + $_y1 = new DDC2231EntityY; + $_y2 = new DDC2231EntityY; + + $_x->data = 'X'; + $_y1->data = 'Y1'; + $_y2->data = 'Y2'; + + $_x->y = array($_y1, $_y2); + $_y1->x = $_x; + $_y2->x = $_x; + + $this->_em->persist($_x); + $this->_em->persist($_y1); + $this->_em->persist($_y2); + + $this->_em->flush(); + $this->_em->clear(); + + $x = $this->_em->find(get_class($_x), $_x->id); + $y1ref = $this->_em->getReference(get_class($_y1), $_y1->id); + + $this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $y1ref); + $this->assertFalse($y1ref->__isInitialized__); + + $y1 = $x->y->get(0); + $this->assertEquals($y1->data, $_y1->data); + $this->assertEquals($this->_em, $y1->om); + + $y2 = $x->y->get(1); + $this->assertEquals($y2->data, $_y2->data); + $this->assertEquals($this->_em, $y2->om); + } +} + + +/** + * @Entity @Table(name="ddc2231_x") + */ +class DDC2231EntityX +{ + /** + * @Id @Column(type="integer") @GeneratedValue + */ + public $id; + /** + * @Column(type="string") + */ + public $data; + /** + * @OneToMany(targetEntity="DDC2231EntityY", mappedBy="x") + */ + public $y; +} + + +/** @Entity @Table(name="ddc2231_y") */ +class DDC2231EntityY implements ObjectManagerAware +{ + /** + * @Id @Column(type="integer") @GeneratedValue + */ + public $id; + /** + * @Column(type="string") + */ + public $data; + /** + * @ManyToOne(targetEntity="DDC2231EntityX", inversedBy="y") + **/ + public $x; + + public $om; + + public function injectObjectManager(ObjectManager $objectManager, ClassMetadata $classMetadata) { + $this->om = $objectManager; + } +} \ No newline at end of file From 3ccbbcb0b5f4bd543e24a4ee5eedc33e8b202d6c Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Sat, 12 Jan 2013 10:29:11 +0100 Subject: [PATCH 4/4] DDC-2231 - Simplify test --- .../ORM/Functional/Ticket/DDC2231Test.php | 76 ++++++------------- 1 file changed, 22 insertions(+), 54 deletions(-) diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2231Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2231Test.php index 822683437..b222e0218 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2231Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2231Test.php @@ -10,75 +10,41 @@ use Doctrine\Common\Persistence\ObjectManagerAware; require_once __DIR__ . '/../../../TestInit.php'; -class DDC237Test extends \Doctrine\Tests\OrmFunctionalTestCase +/** + * @group DDC-2231 + */ +class DDC2231Test extends \Doctrine\Tests\OrmFunctionalTestCase { protected function setUp() { parent::setUp(); $this->_schemaTool->createSchema(array( - $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2231EntityX'), $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2231EntityY'), )); } public function testInjectObjectManagerInProxyIfInitializedInUow() { - $_x = new DDC2231EntityX; - $_y1 = new DDC2231EntityY; - $_y2 = new DDC2231EntityY; + $y1 = new DDC2231EntityY; - $_x->data = 'X'; - $_y1->data = 'Y1'; - $_y2->data = 'Y2'; - - $_x->y = array($_y1, $_y2); - $_y1->x = $_x; - $_y2->x = $_x; - - $this->_em->persist($_x); - $this->_em->persist($_y1); - $this->_em->persist($_y2); + $this->_em->persist($y1); $this->_em->flush(); $this->_em->clear(); - $x = $this->_em->find(get_class($_x), $_x->id); - $y1ref = $this->_em->getReference(get_class($_y1), $_y1->id); + $y1ref = $this->_em->getReference(get_class($y1), $y1->id); $this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $y1ref); $this->assertFalse($y1ref->__isInitialized__); - $y1 = $x->y->get(0); - $this->assertEquals($y1->data, $_y1->data); - $this->assertEquals($this->_em, $y1->om); + $id = $y1ref->doSomething(); - $y2 = $x->y->get(1); - $this->assertEquals($y2->data, $_y2->data); - $this->assertEquals($this->_em, $y2->om); + $this->assertTrue($y1ref->__isInitialized__); + $this->assertEquals($this->_em, $y1ref->om); } } -/** - * @Entity @Table(name="ddc2231_x") - */ -class DDC2231EntityX -{ - /** - * @Id @Column(type="integer") @GeneratedValue - */ - public $id; - /** - * @Column(type="string") - */ - public $data; - /** - * @OneToMany(targetEntity="DDC2231EntityY", mappedBy="x") - */ - public $y; -} - - /** @Entity @Table(name="ddc2231_y") */ class DDC2231EntityY implements ObjectManagerAware { @@ -86,18 +52,20 @@ class DDC2231EntityY implements ObjectManagerAware * @Id @Column(type="integer") @GeneratedValue */ public $id; - /** - * @Column(type="string") - */ - public $data; - /** - * @ManyToOne(targetEntity="DDC2231EntityX", inversedBy="y") - **/ - public $x; public $om; - public function injectObjectManager(ObjectManager $objectManager, ClassMetadata $classMetadata) { + public function injectObjectManager(ObjectManager $objectManager, ClassMetadata $classMetadata) + { $this->om = $objectManager; } -} \ No newline at end of file + + public function getId() + { + return $this->id; + } + + public function doSomething() + { + } +}