From 3407620bf80ec5d09475dcab1f0e089aecfcc064 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Sat, 28 Jan 2012 12:25:01 +0100 Subject: [PATCH] [DDC-1526] Collections are not marked as initialized when they are fetch joined but dont contain any results. This only occurs when using LEFT JOINs on the assocations and causes another query to be fired when the empty collection is accessed again. --- .../ORM/Internal/Hydration/ObjectHydrator.php | 7 +- .../ORM/Functional/Ticket/DDC1526Test.php | 67 +++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1526Test.php diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php index 5595727b0..878c130c2 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php @@ -359,7 +359,6 @@ class ObjectHydrator extends AbstractHydrator continue; } - $parentClass = $this->_ce[$this->_rsm->aliasMap[$parentAlias]]; $oid = spl_object_hash($parentObject); $relationField = $this->_rsm->relationMap[$dqlAlias]; @@ -368,6 +367,7 @@ class ObjectHydrator extends AbstractHydrator // Check the type of the relation (many or single-valued) if ( ! ($relation['type'] & ClassMetadata::TO_ONE)) { + $reflFieldValue = $reflField->getValue($parentObject); // PATH A: Collection-valued association if (isset($nonemptyComponents[$dqlAlias])) { $collKey = $oid . $relationField; @@ -408,9 +408,12 @@ class ObjectHydrator extends AbstractHydrator // Update result pointer $this->_resultPointers[$dqlAlias] = $reflFieldValue[$index]; } - } else if ( ! $reflField->getValue($parentObject)) { + } else if ( ! $reflFieldValue) { $reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField, $parentAlias); + } else if ($reflFieldValue instanceof PersistentCollection && $reflFieldValue->isInitialized() === false) { + $reflFieldValue->setInitialized(true); } + } else { // PATH B: Single-valued association $reflFieldValue = $reflField->getValue($parentObject); diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1526Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1526Test.php new file mode 100644 index 000000000..27d0a87ba --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1526Test.php @@ -0,0 +1,67 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\\DDC1526Menu'), + )); + } + + public function testIssue() + { + $parents = array(); + for ($i = 0; $i < 9; $i++) { + $entity = new DDC1526Menu; + + if (isset ($parents[($i % 3)])) { + $entity->parent = $parents[($i%3)]; + } + + $this->_em->persist($entity); + $parents[$i] = $entity; + } + $this->_em->flush(); + $this->_em->clear(); + + + $dql = "SELECT m, c + FROM " . __NAMESPACE__ . "\DDC1526Menu m + LEFT JOIN m.children c"; + $menus = $this->_em->createQuery($dql)->getResult(); + + // All Children collection now have to be initiailzed + foreach ($menus as $menu) { + $this->assertTrue($menu->children->isInitialized()); + } + } +} + +/** + * @Entity + */ +class DDC1526Menu +{ + /** + * @Column(type="integer") + * @Id + * @GeneratedValue + */ + public $id; + /** + * @ManyToOne(targetEntity="DDC1526Menu", inversedBy="children") + */ + public $parent; + + /** + * @OneToMany(targetEntity="DDC1526Menu", mappedBy="parent") + */ + public $children; +}