1
0
mirror of synced 2025-02-20 06:03:15 +03:00

DDC-2575 Fixed issue with associations when parent is not yet loaded, but child is being created and no link happens.

This commit is contained in:
Guilherme Blanco 2014-04-18 05:21:27 +00:00
parent df806977c6
commit 38b6838386
2 changed files with 182 additions and 12 deletions

View File

@ -404,6 +404,11 @@ class ObjectHydrator extends AbstractHydrator
continue;
}
$parentClass = $this->ce[$this->_rsm->aliasMap[$parentAlias]];
$relationField = $this->_rsm->relationMap[$dqlAlias];
$relation = $parentClass->associationMappings[$relationField];
$reflField = $parentClass->reflFields[$relationField];
// Get a reference to the parent object to which the joined element belongs.
if ($this->_rsm->isMixed && isset($this->rootAliases[$parentAlias])) {
$first = reset($this->resultPointers);
@ -411,20 +416,28 @@ class ObjectHydrator extends AbstractHydrator
} else if (isset($this->resultPointers[$parentAlias])) {
$parentObject = $this->resultPointers[$parentAlias];
} else {
// Parent object of relation not found, so skip it.
// Parent object of relation not found, mark as not-fetched again
$element = $this->getEntity($data, $dqlAlias);
// Update result pointer and provide initial fetch data for parent
$this->resultPointers[$dqlAlias] = $element;
$rowData[$parentAlias][$relationField] = $element;
// Mark as not-fetched again
unset($this->_hints['fetched'][$parentAlias][$relationField]);
////unset($rowData[$dqlAlias]);
//$rowData[$dqlAlias] = $data;
continue;
}
$parentClass = $this->ce[$this->_rsm->aliasMap[$parentAlias]];
$oid = spl_object_hash($parentObject);
$relationField = $this->_rsm->relationMap[$dqlAlias];
$relation = $parentClass->associationMappings[$relationField];
$reflField = $parentClass->reflFields[$relationField];
$oid = spl_object_hash($parentObject);
// 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
$reflFieldValue = $reflField->getValue($parentObject);
if (isset($nonemptyComponents[$dqlAlias])) {
$collKey = $oid . $relationField;
if (isset($this->initializedCollections[$collKey])) {
@ -473,6 +486,7 @@ class ObjectHydrator extends AbstractHydrator
} else {
// PATH B: Single-valued association
$reflFieldValue = $reflField->getValue($parentObject);
if ( ! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH]) || ($reflFieldValue instanceof Proxy && !$reflFieldValue->__isInitialized__)) {
// we only need to take action if this value is null,
// we refresh the entity or its an unitialized proxy.
@ -531,7 +545,7 @@ class ObjectHydrator extends AbstractHydrator
// check for existing result from the iterations before
if ( ! isset($this->identifierMap[$dqlAlias][$id[$dqlAlias]])) {
$element = $this->getEntity($rowData[$dqlAlias], $dqlAlias);
$element = $this->getEntity($data, $dqlAlias);
if ($this->_rsm->isMixed) {
$element = array($entityKey => $element);
@ -566,10 +580,6 @@ class ObjectHydrator extends AbstractHydrator
$index = $this->identifierMap[$dqlAlias][$id[$dqlAlias]];
$this->resultPointers[$dqlAlias] = $result[$index];
$resultKey = $index;
/*if ($this->_rsm->isMixed) {
$result[] = $result[$index];
++$this->_resultCounter;
}*/
}
}
}

View File

@ -0,0 +1,160 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
/**
* @group DDC-2575
*/
class DDC2575Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
private $rootsEntities = array();
private $aEntities = array();
private $bEntities = array();
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2575Root'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2575A'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2575B'),
));
$entityRoot1 = new DDC2575Root(1);
$entityB1 = new DDC2575B(2);
$entityA1 = new DDC2575A($entityRoot1, $entityB1);
$this->_em->persist($entityRoot1);
$this->_em->persist($entityA1);
$this->_em->persist($entityB1);
$entityRoot2 = new DDC2575Root(3);
$entityB2 = new DDC2575B(4);
$entityA2 = new DDC2575A($entityRoot2, $entityB2);
$this->_em->persist($entityRoot2);
$this->_em->persist($entityA2);
$this->_em->persist($entityB2);
$this->_em->flush();
$this->rootsEntities[] = $entityRoot1;
$this->rootsEntities[] = $entityRoot2;
$this->aEntities[] = $entityA1;
$this->aEntities[] = $entityA2;
$this->bEntities[] = $entityB1;
$this->bEntities[] = $entityB2;
$this->_em->clear();
}
public function testHydrationIssue()
{
$repository = $this->_em->getRepository(__NAMESPACE__ . '\DDC2575Root');
$qb = $repository->createQueryBuilder('r')
->select('r, a, b')
->leftJoin('r.aRelation', 'a')
->leftJoin('a.bRelation', 'b');
$query = $qb->getQuery();
$result = $query->getResult();
$this->assertCount(2, $result);
$row = $result[0];
$this->assertNotNull($row->aRelation);
$this->assertEquals(1, $row->id);
$this->assertNotNull($row->aRelation->rootRelation);
$this->assertSame($row, $row->aRelation->rootRelation);
$this->assertNotNull($row->aRelation->bRelation);
$this->assertEquals(2, $row->aRelation->bRelation->id);
$row = $result[1];
$this->assertNotNull($row->aRelation);
$this->assertEquals(3, $row->id);
$this->assertNotNull($row->aRelation->rootRelation);
$this->assertSame($row, $row->aRelation->rootRelation);
$this->assertNotNull($row->aRelation->bRelation);
$this->assertEquals(4, $row->aRelation->bRelation->id);
}
}
/**
* @Entity
*/
class DDC2575Root
{
/**
* @Id
* @Column(type="integer")
*/
public $id;
/**
* @Column(type="integer")
*/
public $sampleField;
/**
* @OneToOne(targetEntity="DDC2575A", mappedBy="rootRelation")
**/
public $aRelation;
public function __construct($id, $value = 0)
{
$this->id = $id;
$this->sampleField = $value;
}
}
/**
* @Entity
*/
class DDC2575A
{
/**
* @Id
* @OneToOne(targetEntity="DDC2575Root", inversedBy="aRelation")
* @JoinColumn(name="root_id", referencedColumnName="id", nullable=FALSE, onDelete="CASCADE")
*/
public $rootRelation;
/**
* @ManyToOne(targetEntity="DDC2575B")
* @JoinColumn(name="b_id", referencedColumnName="id", nullable=FALSE, onDelete="CASCADE")
*/
public $bRelation;
public function __construct(DDC2575Root $rootRelation, DDC2575B $bRelation)
{
$this->rootRelation = $rootRelation;
$this->bRelation = $bRelation;
}
}
/**
* @Entity
*/
class DDC2575B
{
/**
* @Id
* @Column(type="integer")
*/
public $id;
/**
* @Column(type="integer")
*/
public $sampleField;
public function __construct($id, $value = 0)
{
$this->id = $id;
$this->sampleField = $value;
}
}