From 1ae74b8ec56e8749d6c85c2845d64294ba34dd66 Mon Sep 17 00:00:00 2001 From: Heiko Przybyl Date: Thu, 20 Apr 2023 15:37:42 +0200 Subject: [PATCH] Fix single table inheritance with intermediate abstract class(es) Fixes #10625 --- .../Entity/SingleTablePersister.php | 16 ++-- .../ORM/Functional/Ticket/GH10625Test.php | 83 +++++++++++++++++++ 2 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/GH10625Test.php diff --git a/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php b/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php index cbefb6347c3..328a0bdb4b7 100644 --- a/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php +++ b/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php @@ -10,6 +10,9 @@ use Doctrine\ORM\Utility\PersisterHelper; use function array_flip; +use function array_intersect; +use function array_map; +use function array_unshift; use function implode; /** @@ -145,16 +148,13 @@ protected function getSelectConditionCriteriaSQL(Criteria $criteria) /** @return string */ protected function getSelectConditionDiscriminatorValueSQL() { - $values = []; + $values = array_map( + [$this->conn, 'quote'], + array_flip(array_intersect($this->class->discriminatorMap, $this->class->subClasses)) + ); if ($this->class->discriminatorValue !== null) { // discriminators can be 0 - $values[] = $this->conn->quote($this->class->discriminatorValue); - } - - $discrValues = array_flip($this->class->discriminatorMap); - - foreach ($this->class->subClasses as $subclassName) { - $values[] = $this->conn->quote($discrValues[$subclassName]); + array_unshift($values, $this->conn->quote($this->class->discriminatorValue)); } $discColumnName = $this->class->getDiscriminatorColumn()['name']; diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/GH10625Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH10625Test.php new file mode 100644 index 00000000000..13f3a544b48 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH10625Test.php @@ -0,0 +1,83 @@ +createSchemaForModels( + GH10625Root::class, + GH10625Middle::class, + GH10625Leaf::class + ); + } + + /** + * @dataProvider queryClasses + */ + public function testLoadFieldsFromAllClassesInHierarchy(string $queryClass): void + { + $entity = new GH10625Leaf(); + + $this->_em->persist($entity); + $this->_em->flush(); + $this->_em->clear(); + + $loadedEntity = $this->_em->find($queryClass, $entity->id); + + self::assertNotNull($loadedEntity); + self::assertInstanceOf(GH10625Leaf::class, $loadedEntity); + } + + public static function queryClasses(): array + { + return [ + 'query via root entity' => [GH10625Root::class], + 'query via intermediate entity' => [GH10625Middle::class], + 'query via leaf entity' => [GH10625Leaf::class], + ]; + } +} + +/** + * @ORM\Entity + * @ORM\InheritanceType("SINGLE_TABLE") + * @ORM\DiscriminatorMap({ "1": "GH10625Leaf"}) + * ^- This DiscriminatorMap contains the single non-abstract Entity class only + */ +abstract class GH10625Root +{ + /** + * @ORM\Id + * @ORM\GeneratedValue(strategy="AUTO") + * @ORM\Column(type="integer") + * + * @var int + */ + public $id; +} + +/** + * @ORM\Entity + */ +abstract class GH10625Middle extends GH10625Root +{ +} + +/** + * @ORM\Entity + */ +class GH10625Leaf extends GH10625Middle +{ +}