diff --git a/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php index 8ce4c03ce11..2a57fc7e8c4 100644 --- a/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php @@ -1933,20 +1933,7 @@ private function getValues($value): array return [$newValue]; } - if (is_object($value) && $this->em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) { - $class = $this->em->getClassMetadata(get_class($value)); - if ($class->isIdentifierComposite) { - $newValue = []; - - foreach ($class->getIdentifierValues($value) as $innerValue) { - $newValue = array_merge($newValue, $this->getValues($innerValue)); - } - - return $newValue; - } - } - - return [$this->getIndividualValue($value)]; + return $this->getIndividualValue($value); } /** @@ -1954,15 +1941,34 @@ private function getValues($value): array * * @param mixed $value * - * @return mixed + * @return array + * @psalm-return list */ private function getIndividualValue($value) { - if (! is_object($value) || ! $this->em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) { - return $value; + if (! is_object($value)) { + return [$value]; + } + + $valueClass = ClassUtils::getClass($value); + + if ($this->em->getMetadataFactory()->isTransient($valueClass)) { + return [$value]; + } + + $class = $this->em->getClassMetadata($valueClass); + + if ($class->isIdentifierComposite) { + $newValue = []; + + foreach ($class->getIdentifierValues($value) as $innerValue) { + $newValue = array_merge($newValue, $this->getValues($innerValue)); + } + + return $newValue; } - return $this->em->getUnitOfWork()->getSingleIdentifierValue($value); + return [$this->em->getUnitOfWork()->getSingleIdentifierValue($value)]; } /** diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/GH7512Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH7512Test.php new file mode 100644 index 00000000000..d390d50899c --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH7512Test.php @@ -0,0 +1,97 @@ +setUpEntitySchema([ + GH7512EntityA::class, + GH7512EntityB::class, + GH7512EntityC::class, + ]); + + $this->_em->persist(new GH7512EntityA()); + $this->_em->persist(new GH7512EntityC()); + $this->_em->flush(); + $this->_em->clear(); + } + + public function testFindEntityByAssociationPropertyJoinedChildWithClearMetadata(): void + { + // unset metadata for entity B as though it hasn't been touched yet in application lifecycle. + $this->_em->getMetadataFactory()->setMetadataFor(GH7512EntityB::class, null); + $result = $this->_em->getRepository(GH7512EntityC::class)->findBy([ + 'entityA' => new GH7512EntityB(), + ]); + $this->assertEmpty($result); + } +} + +/** + * @Entity() + * @InheritanceType("JOINED") + * @DiscriminatorMap({ + * "entitya"=Doctrine\Tests\ORM\Functional\Ticket\GH7512EntityA::class, + * "entityB"=Doctrine\Tests\ORM\Functional\Ticket\GH7512EntityB::class + * }) + */ +class GH7512EntityA +{ + /** + * @Column(type="integer") + * @Id() + * @GeneratedValue(strategy="AUTO") + * @var int + */ + public $id; + + /** + * @OneToMany(targetEntity="Doctrine\Tests\ORM\Functional\Ticket\GH7512EntityC", mappedBy="entityA") + * @var Collection + */ + public $entityCs; +} + +/** + * @Entity() + */ +class GH7512EntityB extends GH7512EntityA +{ +} + +/** + * @Entity() + */ +class GH7512EntityC +{ + /** + * @Column(type="integer") + * @Id() + * @GeneratedValue(strategy="AUTO") + * @var int + */ + public $id; + + /** + * @ManyToOne(targetEntity="Doctrine\Tests\ORM\Functional\Ticket\GH7512EntityA", inversedBy="entityCs") + * @var GH7512EntityA + */ + public $entityA; +}