Skip to content

Commit

Permalink
Merge branch 'fix/#6988-#6304-ensure-inheritance-middle-layer-is-hydr…
Browse files Browse the repository at this point in the history
…ated'

Close #6988
Close #6304
  • Loading branch information
Ocramius committed Feb 19, 2018
2 parents 92445d0 + bbf0c03 commit 0822f8a
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 3 deletions.
25 changes: 22 additions & 3 deletions lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
Expand Up @@ -12,7 +12,9 @@
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\ORM\UnitOfWork;
use function array_map;
use function array_merge;
use function in_array;

/**
* Base class for all hydrators. A hydrator is a class that provides some form
Expand Down Expand Up @@ -272,9 +274,8 @@ protected function gatherRowData(array $data, array &$id, array &$nonemptyCompon

// If there are field name collisions in the child class, then we need
// to only hydrate if we are looking at the correct discriminator value
if (isset($cacheKeyInfo['discriminatorColumn'], $data[$cacheKeyInfo['discriminatorColumn']]) &&
// Note: loose comparison required. See https://github.com/doctrine/doctrine2/pull/6304#issuecomment-323294442
$data[$cacheKeyInfo['discriminatorColumn']] != $cacheKeyInfo['discriminatorValue'] // TODO get rid of loose comparison
if (isset($cacheKeyInfo['discriminatorColumn'], $data[$cacheKeyInfo['discriminatorColumn']])
&& ! in_array((string) $data[$cacheKeyInfo['discriminatorColumn']], $cacheKeyInfo['discriminatorValues'], true)
) {
break;
}
Expand Down Expand Up @@ -378,6 +379,7 @@ protected function hydrateColumnInfo($key)
[
'discriminatorColumn' => $this->rsm->discriminatorColumns[$ownerMap],
'discriminatorValue' => $classMetadata->discriminatorValue,
'discriminatorValues' => $this->getDiscriminatorValues($classMetadata),
]
);
}
Expand Down Expand Up @@ -427,6 +429,23 @@ protected function hydrateColumnInfo($key)
return null;
}

/**
* @return string[]
*/
private function getDiscriminatorValues(ClassMetadata $classMetadata) : array
{
$values = array_map(
function (string $subClass) : string {
return (string) $this->getClassMetadata($subClass)->discriminatorValue;
},
$classMetadata->getSubClasses()
);

$values[] = (string) $classMetadata->discriminatorValue;

return $values;
}

/**
* Retrieve ClassMetadata associated to entity class name.
*
Expand Down
126 changes: 126 additions & 0 deletions tests/Doctrine/Tests/ORM/Functional/Ticket/GH6937Test.php
@@ -0,0 +1,126 @@
<?php

namespace Doctrine\Tests\ORM\Functional\Ticket;

use Doctrine\ORM\AbstractQuery;
use Doctrine\Tests\OrmFunctionalTestCase;
use Doctrine\ORM\Annotation as ORM;

/**
* @group 6937
*/
final class GH6937Test extends OrmFunctionalTestCase
{
/**
* {@inheritDoc}
*/
protected function setUp() : void
{
parent::setUp();

$this->setUpEntitySchema([GH6937Person::class, GH6937Employee::class, GH6937Manager::class]);
}

public function testPhoneNumberIsPopulatedWithFind() : void
{
$manager = new GH6937Manager();
$manager->name = 'Kevin';
$manager->phoneNumber = '555-5555';
$manager->department = 'Accounting';

$this->em->persist($manager);
$this->em->flush();
$this->em->clear();

$persistedManager = $this->em->find(GH6937Person::class, $manager->id);

self::assertSame('Kevin', $persistedManager->name);
self::assertSame('555-5555', $persistedManager->phoneNumber);
self::assertSame('Accounting', $persistedManager->department);
}

public function testPhoneNumberIsPopulatedWithQueryBuilderUsingSimpleObjectHydrator() : void
{
$manager = new GH6937Manager();
$manager->name = 'Kevin';
$manager->phoneNumber = '555-5555';
$manager->department = 'Accounting';

$this->em->persist($manager);
$this->em->flush();
$this->em->clear();

$persistedManager = $this
->em
->createQueryBuilder()
->select('e')
->from(GH6937Person::class, 'e')
->where('e.id = :id')
->setParameter('id', $manager->id)
->getQuery()
->getOneOrNullResult(AbstractQuery::HYDRATE_SIMPLEOBJECT);

self::assertSame('Kevin', $persistedManager->name);
self::assertSame('555-5555', $persistedManager->phoneNumber);
self::assertSame('Accounting', $persistedManager->department);
}

public function testPhoneNumberIsPopulatedWithQueryBuilder() : void
{
$manager = new GH6937Manager();
$manager->name = 'Kevin';
$manager->phoneNumber = '555-5555';
$manager->department = 'Accounting';

$this->em->persist($manager);
$this->em->flush();
$this->em->clear();

$persistedManager = $this
->em
->createQueryBuilder()
->select('e')
->from(GH6937Person::class, 'e')
->where('e.id = :id')
->setParameter('id', $manager->id)
->getQuery()
->getOneOrNullResult();

self::assertSame('Kevin', $persistedManager->name);
self::assertSame('555-5555', $persistedManager->phoneNumber);
self::assertSame('Accounting', $persistedManager->department);
}
}

/**
* @ORM\Entity
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({"employee"=GH6937Employee::class, "manager"=GH6937Manager::class})
*/
abstract class GH6937Person
{
/** @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue */
public $id;

/** @ORM\Column(type="string") */
public $name;
}

/**
* @ORM\Entity
*/
abstract class GH6937Employee extends GH6937Person
{
/** @ORM\Column(type="string") */
public $phoneNumber;
}

/**
* @ORM\Entity
*/
class GH6937Manager extends GH6937Employee
{
/** @ORM\Column(type="string") */
public $department;
}

0 comments on commit 0822f8a

Please sign in to comment.