Skip to content

Commit

Permalink
Check if association already contains object (#9579)
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Bartels committed Mar 18, 2022
1 parent 82bbb1d commit 64a0f85
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 2 deletions.
7 changes: 5 additions & 2 deletions lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,11 @@ protected function hydrateRowData(array $row, array &$result)
$reflFieldValue->hydrateSet($indexValue, $element);
$this->identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $indexValue;
} else {
$reflFieldValue->hydrateAdd($element);
$reflFieldValue->last();
if (! $reflFieldValue->contains($element)) {
$reflFieldValue->hydrateAdd($element);
$reflFieldValue->last();
}

$this->identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $reflFieldValue->key();
}

Expand Down
182 changes: 182 additions & 0 deletions tests/Doctrine/Tests/ORM/Functional/Ticket/GH9579Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
<?php

declare(strict_types=1);

namespace Doctrine\Tests\ORM\Functional\Ticket;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\OneToOne;
use Doctrine\ORM\Mapping\Table;
use Doctrine\Tests\OrmFunctionalTestCase;

/**
* @group GH-9579
*/
class GH9579Test extends OrmFunctionalTestCase
{
protected function setUp(): void
{
parent::setUp();

$this->_schemaTool->createSchemaForModels(
GH9579Container::class,
GH9579Item::class,
GH9579Part::class,
);

$container = new GH9579Container();

$item = new GH9579Item();
$item->container = $container;

$container->currentItem = $item;

$part = new GH9579Part();
$part->item = $item;

$this->_em->persist($item);
$this->_em->persist($container);
$this->_em->persist($part);

$this->_em->flush();
$this->_em->clear();
}

/**
* @group GH-9579
*/
public function testIssue(): void
{
$dql = <<<'DQL'
SELECT container, currentItem, currentItemPart, item, itemPart
FROM Doctrine\Tests\ORM\Functional\Ticket\GH9579Container container
LEFT JOIN container.currentItem currentItem
LEFT JOIN currentItem.parts currentItemPart
LEFT JOIN container.items item
LEFT JOIN item.parts itemPart
DQL;
$containers = $this->_em->createQuery($dql)->execute();
self::assertCount(1, $containers);
self::assertCount(1, $containers[0]->items);
self::assertCount(1, $containers[0]->items[0]->parts);
}

/**
* @group GH-9579
*/
public function testIfAlreadyManaged(): void
{
$containers = $this->_em->getRepository(GH9579Container::class)->findAll();
self::assertCount(1, $containers);
self::assertCount(1, $containers[0]->items);
self::assertCount(1, $containers[0]->items[0]->parts);

$dql = <<<'DQL'
SELECT container, currentItem, currentItemPart, item, itemPart
FROM Doctrine\Tests\ORM\Functional\Ticket\GH9579Container container
LEFT JOIN container.currentItem currentItem
LEFT JOIN currentItem.parts currentItemPart
LEFT JOIN container.items item
LEFT JOIN item.parts itemPart
DQL;
$containers = $this->_em->createQuery($dql)->execute();
self::assertCount(1, $containers);
self::assertCount(1, $containers[0]->items);
self::assertCount(1, $containers[0]->items[0]->parts);
}
}

/**
* @Entity
* @Table(name="GH9579_containers")
*/
class GH9579Container
{
/**
* @Id
* @Column(type="integer")
* @GeneratedValue
* @var int
*/
public $id;

/**
* @var Collection<int, GH9579Item>
* @OneToMany (targetEntity="GH9579Item", mappedBy="container")
*/
public $items;

public function __construct()
{
$this->items = new ArrayCollection();
}

/**
* @var GH9579Item
* @OneToOne(targetEntity="GH9579Item")
* @JoinColumn(name="item_id", referencedColumnName="id")
*/
public $currentItem;
}

/**
* @Entity
* @Table(name="GH9579_items")
*/
class GH9579Item
{
public function __construct()
{
$this->parts = new ArrayCollection();
}

/**
* @Id
* @Column(type="integer")
* @GeneratedValue
* @var int
*/
public $id;

/**
* @var Collection<int, GH9579Part>
* @OneToMany(targetEntity="GH9579Part", mappedBy="item")
*/
public $parts;

/**
* @var GH9579Container
* @ManyToOne (targetEntity="GH9579Container", inversedBy="items")
* @JoinColumn(name="container_id", referencedColumnName="id")
*/
public $container;
}

/**
* @Entity
* @Table(name="GH9579_parts")
*/
class GH9579Part
{
/**
* @Id
* @Column(type="integer")
* @GeneratedValue
* @var int
*/
public $id;

/**
* @var GH9579Item
* @ManyToOne (targetEntity="GH9579Item", inversedBy="parts")
* @JoinColumn(name="item_id", referencedColumnName="id")
*/
public $item;
}

0 comments on commit 64a0f85

Please sign in to comment.