diff --git a/src/Persisters/Entity/AbstractEntityInheritancePersister.php b/src/Persisters/Entity/AbstractEntityInheritancePersister.php index b17b30dbbef..e178a4b7689 100644 --- a/src/Persisters/Entity/AbstractEntityInheritancePersister.php +++ b/src/Persisters/Entity/AbstractEntityInheritancePersister.php @@ -45,13 +45,21 @@ protected function getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r' { $tableAlias = $alias === 'r' ? '' : $alias; $fieldMapping = $class->fieldMappings[$field]; - $columnAlias = $this->getSQLColumnAlias($fieldMapping['columnName']); $sql = sprintf( '%s.%s', $this->getSQLTableAlias($class->name, $tableAlias), $this->quoteStrategy->getColumnName($field, $class, $this->platform) ); + $columnAlias = null; + if ($this->currentPersisterContext->rsm->hasColumnAliasByField($alias, $field)) { + $columnAlias = $this->currentPersisterContext->rsm->getColumnAliasByField($alias, $field); + } + + if ($columnAlias === null) { + $columnAlias = $this->getSQLColumnAlias($fieldMapping['columnName']); + } + $this->currentPersisterContext->rsm->addFieldResult($alias, $columnAlias, $field, $class->name); if (isset($fieldMapping['requireSQLConversion'])) { diff --git a/src/Query/ResultSetMapping.php b/src/Query/ResultSetMapping.php index 1f3c1843f51..b3235fa3498 100644 --- a/src/Query/ResultSetMapping.php +++ b/src/Query/ResultSetMapping.php @@ -356,6 +356,10 @@ public function addFieldResult($alias, $columnName, $fieldName, $declaringClass public function hasColumnAliasByField(string $alias, string $fieldName): bool { + if (! isset($this->aliasMap[$alias])) { + return false; + } + $declaringClass = $this->aliasMap[$alias]; return isset($this->columnAliasMappings[$declaringClass][$alias][$fieldName]); diff --git a/tests/Tests/DbalTypes/Rot13Type.php b/tests/Tests/DbalTypes/Rot13Type.php index 679eb3ed141..6a38d011de0 100644 --- a/tests/Tests/DbalTypes/Rot13Type.php +++ b/tests/Tests/DbalTypes/Rot13Type.php @@ -18,8 +18,7 @@ class Rot13Type extends Type /** * {@inheritDoc} * - * @param string|null $value - * @param AbstractPlatform $platform + * @param string|null $value * * @return string|null */ @@ -35,8 +34,7 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform) /** * {@inheritDoc} * - * @param string|null $value - * @param AbstractPlatform $platform + * @param string|null $value * * @return string|null */ @@ -52,9 +50,6 @@ public function convertToPHPValue($value, AbstractPlatform $platform) /** * {@inheritDoc} * - * @param array $fieldDeclaration - * @param AbstractPlatform $platform - * * @return string */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) @@ -69,8 +64,6 @@ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $pla /** * {@inheritDoc} * - * @param AbstractPlatform $platform - * * @return int|null */ public function getDefaultLength(AbstractPlatform $platform) diff --git a/tests/Tests/ORM/Functional/Ticket/GH12225/AbstractDirectory.php b/tests/Tests/ORM/Functional/Ticket/GH12225/AbstractDirectory.php new file mode 100644 index 00000000000..ad76dc6317a --- /dev/null +++ b/tests/Tests/ORM/Functional/Ticket/GH12225/AbstractDirectory.php @@ -0,0 +1,123 @@ + ConcreteDirectory::class])] +class AbstractDirectory +{ + /** + * @var int + * @Id + * @GeneratedValue + * @Column(name="id", type="integer") + */ + #[Id] + #[GeneratedValue] + #[Column(name: 'id', type: 'integer')] + private $id; + + /** + * @var string + * @Column(name="dir_key", type="string") + */ + #[Column(name: 'dir_key', type: 'string')] + private $dirKey; + + /** + * @var DateTimeImmutable|null + * @Column(name="deleted_at", type="datetime_immutable", nullable=true) + */ + #[Column(name: 'deleted_at', type: 'datetime_immutable', nullable: true)] + private $deletedAt = null; + + /** + * @var AbstractDirectory|null + * @ManyToOne(targetEntity=AbstractDirectory::class, fetch="LAZY", inversedBy="directories") + */ + #[ManyToOne(targetEntity: self::class, fetch: 'LAZY', inversedBy: 'directories')] + private $parent = null; + + /** + * @var Collection + * @OneToMany(mappedBy="parent", targetEntity=AbstractDirectory::class, fetch="EXTRA_LAZY", indexBy="dirKey") + */ + #[OneToMany(mappedBy: 'parent', targetEntity: self::class, fetch: 'EXTRA_LAZY', indexBy: 'dirKey')] + private $children; + + public function __construct(string $dirKey) + { + $this->dirKey = $dirKey; + $this->children = new ArrayCollection(); + } + + public function getId(): int + { + return $this->id; + } + + public function getDirKey(): string + { + return $this->dirKey; + } + + public function getDeletedAt(): ?DateTimeImmutable + { + return $this->deletedAt; + } + + public function setDeletedAt(?DateTimeImmutable $deletedAt): AbstractDirectory + { + $this->deletedAt = $deletedAt; + + return $this; + } + + public function getParent(): ?AbstractDirectory + { + return $this->parent; + } + + public function setParent(?AbstractDirectory $parent): AbstractDirectory + { + $this->parent = $parent; + + return $this; + } + + /** + * @return Collection + */ + public function getChildren(): Collection + { + return $this->children; + } +} diff --git a/tests/Tests/ORM/Functional/Ticket/GH12225/ConcreteDirectory.php b/tests/Tests/ORM/Functional/Ticket/GH12225/ConcreteDirectory.php new file mode 100644 index 00000000000..327253f15e6 --- /dev/null +++ b/tests/Tests/ORM/Functional/Ticket/GH12225/ConcreteDirectory.php @@ -0,0 +1,15 @@ +setUpEntitySchema([ + AbstractDirectory::class, + ConcreteDirectory::class, + ]); + } + + public function testHydrateWithIndexByFilterAndInheritanceMapping(): void + { + // Enable the filter + $this->_em->getConfiguration()->addFilter('my_filter', MyFilter::class); + $this->_em->getFilters()->enable('my_filter'); + + // Load entities into database + $parent = new ConcreteDirectory('parent'); + $child = (new ConcreteDirectory('child'))->setParent($parent); + $this->_em->persist($parent); + $this->_em->persist($child); + $this->_em->flush(); + $this->_em->clear(); + + $repository = $this->_em->getRepository(AbstractDirectory::class); + + // Fetch entities from database while changing filters + $this->_em->getFilters()->suspend('my_filter'); + $directories = $repository->findBy(['parent' => null]); + $this->_em->getFilters()->restore('my_filter'); + + // Ensure we got the parent directory + self::assertCount(1, $directories); + self::assertEquals('parent', $directories[0]->getDirKey()); + + // Try to hydrate all children of the parent directory (toArray is important here to initialize the collection) + self::assertCount(1, $directories[0]->getChildren()->toArray()); + } +} diff --git a/tests/Tests/ORM/Functional/Ticket/GH12225/MyFilter.php b/tests/Tests/ORM/Functional/Ticket/GH12225/MyFilter.php new file mode 100644 index 00000000000..9b5f45903c9 --- /dev/null +++ b/tests/Tests/ORM/Functional/Ticket/GH12225/MyFilter.php @@ -0,0 +1,16 @@ +