From 7986fc64dd1daef50c3a90915ee5bd236a08fea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20Mart=C3=ADnez?= Date: Wed, 28 Jun 2023 15:43:23 +0200 Subject: [PATCH] Verify UnitOfWork::HINT_DEFEREAGERLOAD exists and is true --- lib/Doctrine/ORM/UnitOfWork.php | 4 +- .../ORM/Functional/Ticket/GH10808Test.php | 107 ++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/GH10808Test.php diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index cc1c5ab22bc..a1c0faad5af 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -2976,7 +2976,9 @@ public function createEntity($className, array $data, &$hints = []) break; // Deferred eager load only works for single identifier classes - case isset($hints[self::HINT_DEFEREAGERLOAD]) && ! $targetClass->isIdentifierComposite: + case isset($hints[self::HINT_DEFEREAGERLOAD]) && + $hints[self::HINT_DEFEREAGERLOAD] && + ! $targetClass->isIdentifierComposite: // TODO: Is there a faster approach? $this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($normalizedAssociatedId); diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/GH10808Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH10808Test.php new file mode 100644 index 00000000000..a2ff78f43a9 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/GH10808Test.php @@ -0,0 +1,107 @@ +createSchemaForModels( + GH10808Appointment::class, + GH10808AppointmentChild::class + ); + } + + public function testDQLDeferredEagerLoad(): void + { + $appointment = new GH10808Appointment(); + + $this->_em->persist($appointment); + $this->_em->flush(); + $this->_em->clear(); + + $query = $this->_em->createQuery( + 'SELECT appointment from Doctrine\Tests\ORM\Functional\Ticket\GH10808Appointment appointment + JOIN appointment.child appointment_child + WITH appointment_child.id = 1' + ); + + // By default, UnitOfWork::HINT_DEFEREAGERLOAD is set to 'true' + $deferredLoadResult = $query->getSingleResult(); + + // Clear the EM to prevent the recovery of the loaded instance, which would otherwise result in a proxy. + $this->_em->clear(); + + $eagerLoadResult = $query->setHint(UnitOfWork::HINT_DEFEREAGERLOAD, false)->getSingleResult(); + + self::assertNotEquals( + GH10808AppointmentChild::class, + get_class($deferredLoadResult->child), + '$deferredLoadResult->child should be a proxy' + ); + self::assertEquals( + GH10808AppointmentChild::class, + get_class($eagerLoadResult->child), + '$eagerLoadResult->child should not be a proxy' + ); + } +} + +/** + * @Entity + * @Table(name="gh10808_appointment") + */ +class GH10808Appointment +{ + /** + * @var int + * @Id + * @Column(type="integer") + * @GeneratedValue + */ + public $id; + + /** + * @var GH10808AppointmentChild + * @OneToOne(targetEntity="GH10808AppointmentChild", cascade={"persist", "remove"}, fetch="EAGER") + * @JoinColumn(name="child_id", referencedColumnName="id") + */ + public $child; + + public function __construct() + { + $this->child = new GH10808AppointmentChild(); + } +} + +/** + * @Entity + * @Table(name="gh10808_appointment_child") + */ +class GH10808AppointmentChild +{ + /** + * @var int + * @Id + * @Column(type="integer") + * @GeneratedValue + */ + private $id; +}