diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php index 26f9e163e..50dbbc449 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php @@ -126,13 +126,12 @@ class ObjectHydrator extends AbstractHydrator * @param object $entity The entity to which the collection belongs. * @param string $name The name of the field on the entity that holds the collection. */ - private function _initRelatedCollection($entity, $name) + private function _initRelatedCollection($entity, $class, $fieldName) { $oid = spl_object_hash($entity); - $class = $this->_ce[get_class($entity)]; - $relation = $class->associationMappings[$name]; + $relation = $class->associationMappings[$fieldName]; - $value = $class->reflFields[$name]->getValue($entity); + $value = $class->reflFields[$fieldName]->getValue($entity); if ($value === null) { $value = new ArrayCollection; } @@ -144,18 +143,18 @@ class ObjectHydrator extends AbstractHydrator $value ); $value->setOwner($entity, $relation); - $class->reflFields[$name]->setValue($entity, $value); - $this->_uow->setOriginalEntityProperty($oid, $name, $value); - $this->_initializedCollections[$oid . $name] = $value; + $class->reflFields[$fieldName]->setValue($entity, $value); + $this->_uow->setOriginalEntityProperty($oid, $fieldName, $value); + $this->_initializedCollections[$oid . $fieldName] = $value; } else if (isset($this->_hints[Query::HINT_REFRESH])) { // Is already PersistentCollection, but REFRESH $value->clear(); $value->setDirty(false); $value->setInitialized(true); - $this->_initializedCollections[$oid . $name] = $value; + $this->_initializedCollections[$oid . $fieldName] = $value; } else { // Is already PersistentCollection, and DONT REFRESH - $this->_existingCollections[$oid . $name] = $value; + $this->_existingCollections[$oid . $fieldName] = $value; } return $value; @@ -266,11 +265,11 @@ class ObjectHydrator extends AbstractHydrator continue; } - $parentClass = $this->_rsm->aliasMap[$parentAlias]; + $parentClass = $this->_ce[$this->_rsm->aliasMap[$parentAlias]]; $oid = spl_object_hash($parentObject); $relationField = $this->_rsm->relationMap[$dqlAlias]; - $relation = $this->_ce[$parentClass]->associationMappings[$relationField]; - $reflField = $this->_ce[$parentClass]->reflFields[$relationField]; + $relation = $parentClass->associationMappings[$relationField]; + $reflField = $parentClass->reflFields[$relationField]; // Check the type of the relation (many or single-valued) if ( ! $relation->isOneToOne()) { @@ -280,7 +279,7 @@ class ObjectHydrator extends AbstractHydrator if (isset($this->_initializedCollections[$collKey])) { $reflFieldValue = $this->_initializedCollections[$collKey]; } else if ( ! isset($this->_existingCollections[$collKey])) { - $reflFieldValue = $this->_initRelatedCollection($parentObject, $relationField); + $reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField); } $indexExists = isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]]); @@ -304,11 +303,11 @@ class ObjectHydrator extends AbstractHydrator if ($relation->isOwningSide && isset($this->_ce[$entityName]->inverseMappings[$relation->sourceEntityName][$relationField])) { $inverseFieldName = $this->_ce[$entityName]->inverseMappings[$relation->sourceEntityName][$relationField]->sourceFieldName; if ( ! isset($this->_initializedCollections[spl_object_hash($element) . $inverseFieldName])) { - $this->_initRelatedCollection($element, $inverseFieldName); + $this->_initRelatedCollection($element, $this->_ce[$entityName], $inverseFieldName); } } else if ($relation->mappedByFieldName) { if ( ! isset($this->_initializedCollections[spl_object_hash($element) . $relation->mappedByFieldName])) { - $this->_initRelatedCollection($element, $relation->mappedByFieldName); + $this->_initRelatedCollection($element, $this->_ce[$entityName], $relation->mappedByFieldName); } } } @@ -351,12 +350,12 @@ class ObjectHydrator extends AbstractHydrator if ($inverseAssoc->isOneToMany()) { // Only initialize reverse collection if it is not yet initialized. if ( ! isset($this->_initializedCollections[spl_object_hash($element) . $inverseAssoc->sourceFieldName])) { - $this->_initRelatedCollection($element, $inverseAssoc->sourceFieldName); + $this->_initRelatedCollection($element, $targetClass, $inverseAssoc->sourceFieldName); } } else { $targetClass->reflFields[$inverseAssoc->sourceFieldName]->setValue($element, $parentObject); } - } else if ($this->_ce[$parentClass] === $targetClass && $relation->mappedByFieldName) { + } else if ($parentClass === $targetClass && $relation->mappedByFieldName) { // Special case: bi-directional self-referencing one-one on the same class $targetClass->reflFields[$relationField]->setValue($element, $parentObject); } diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC199Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC199Test.php new file mode 100644 index 000000000..c9e129a03 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC199Test.php @@ -0,0 +1,100 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC199ParentClass'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC199ChildClass'), + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC199RelatedClass') + )); + } + + public function testPolymorphicLoading() + { + $child = new DDC199ChildClass; + $child->parentData = 'parentData'; + $child->childData = 'childData'; + $this->_em->persist($child); + + $related1 = new DDC199RelatedClass; + $related1->relatedData = 'related1'; + $related1->parent = $child; + $this->_em->persist($related1); + + $related2 = new DDC199RelatedClass; + $related2->relatedData = 'related2'; + $related2->parent = $child; + $this->_em->persist($related2); + + $this->_em->flush(); + $this->_em->clear(); + + $query = $this->_em->createQuery('select e,r from Doctrine\Tests\ORM\Functional\Ticket\DDC199ParentClass e join e.relatedEntities r'); + $result = $query->getResult(); + + $this->assertEquals(1, count($result)); + $this->assertTrue($result[0] instanceof DDC199ChildClass); + $this->assertTrue($result[0]->relatedEntities->isInitialized()); + $this->assertEquals(2, $result[0]->relatedEntities->count()); + $this->assertTrue($result[0]->relatedEntities[0] instanceof DDC199RelatedClass); + $this->assertTrue($result[0]->relatedEntities[1] instanceof DDC199RelatedClass); + } +} + + +/** + * @Entity @Table(name="ddc199_entities") + * @InheritanceType("SINGLE_TABLE") + * @DiscriminatorColumn(name="discr", type="string") + * @DiscriminatorMap({"parent" = "DDC199ParentClass", "child" = "DDC199ChildClass"}) + */ +class DDC199ParentClass +{ + /** + * @Id @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + public $id; + + /** + * @Column(type="string") + */ + public $parentData; + + /** + * @OneToMany(targetEntity="DDC199RelatedClass", mappedBy="parent") + */ + public $relatedEntities; +} + + +/** @Entity */ +class DDC199ChildClass extends DDC199ParentClass +{ + /** + * @Column(type="string") + */ + public $childData; +} + +/** @Entity @Table(name="ddcxxx_relatedclass") */ +class DDC199RelatedClass +{ + /** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */ + public $id; + /** @Column(type="string") */ + public $relatedData; + + /** + * @ManyToOne(targetEntity="DDC199ParentClass") + * @JoinColumn(name="parent_id", referencedColumnName="id") + */ + public $parent; +} \ No newline at end of file