From d33332cb9e7aededfb73a3cbf362490ee1e77ca4 Mon Sep 17 00:00:00 2001 From: Guy Sartorelli <36352093+GuySartorelli@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:57:22 +1300 Subject: [PATCH] FIX Add eagerloaded data to ALL relevant lists (#11139) --- src/ORM/DataList.php | 2 +- src/ORM/EagerLoadedList.php | 2 +- tests/php/ORM/DataListEagerLoadingTest.php | 35 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/ORM/DataList.php b/src/ORM/DataList.php index edc3c040cf9..c7cfc745dc9 100644 --- a/src/ORM/DataList.php +++ b/src/ORM/DataList.php @@ -1372,7 +1372,7 @@ private function addEagerLoadedDataToParent( if ($parentData->hasID($parentID)) { $parentData->addEagerLoadedData($relationName, $parentID, $eagerLoadedData); $added = true; - break; + // can't break here, because the parent might be in multiple relation lists } } else { throw new LogicException("Invalid parent for eager loading $relationType relation $relationName"); diff --git a/src/ORM/EagerLoadedList.php b/src/ORM/EagerLoadedList.php index 6464aea8018..902a1860843 100644 --- a/src/ORM/EagerLoadedList.php +++ b/src/ORM/EagerLoadedList.php @@ -940,7 +940,7 @@ private function setDataObjectEagerLoadedData(int $id, DataObject $item): void /** * Gets the final rows for this list after applying all transformations. - * Currently only limit is applied lazily, but others could be done this was as well. + * Currently only limit and sort are applied lazily, but filter could be done this was as well in the future. */ private function getFinalisedRows(): array { diff --git a/tests/php/ORM/DataListEagerLoadingTest.php b/tests/php/ORM/DataListEagerLoadingTest.php index 2871ce834b7..b27bf050fac 100644 --- a/tests/php/ORM/DataListEagerLoadingTest.php +++ b/tests/php/ORM/DataListEagerLoadingTest.php @@ -1254,4 +1254,39 @@ public function testLastHasEagerloadedRelation() $obj = EagerLoadObject::get()->eagerLoad('HasManyEagerLoadObjects')->last(); $this->assertInstanceOf(EagerLoadedList::class, $obj->HasManyEagerLoadObjects()); } + + /** + * Tests that if the same record exists in multiple relations, its data is + * eagerloaded without extra unnecessary queries. + */ + public function testEagerLoadingSharedRelations() + { + $record1 = EagerLoadObject::create(['Title' => 'My obj1']); + $record1->write(); + $record2 = EagerLoadObject::create(['Title' => 'My obj2']); + $record2->write(); + $manyMany = ManyManyEagerLoadObject::create(['Title' => 'My manymany']); + $manyMany->write(); + $record1->ManyManyEagerLoadObjects()->add($manyMany); + $record2->ManyManyEagerLoadObjects()->add($manyMany); + $subManyMany = ManyManySubEagerLoadObject::create(['Title' => 'My submanymany']); + $subManyMany->write(); + $manyMany->ManyManySubEagerLoadObjects()->add($subManyMany); + + $eagerLoadQuery = EagerLoadObject::get() + ->filter(['ID' => [$record1->ID, $record2->ID]]) + ->eagerLoad('ManyManyEagerLoadObjects.ManyManySubEagerLoadObjects'); + $loop1Count = 0; + $loop2Count = 0; + foreach ($eagerLoadQuery as $record) { + $loop1Count++; + $eagerLoaded1 = $record->ManyManyEagerLoadObjects(); + $this->assertInstanceOf(EagerLoadedList::class, $eagerLoaded1); + foreach ($eagerLoaded1 as $manyManyRecord) { + $loop2Count++; + $eagerLoaded2 = $manyManyRecord->ManyManySubEagerLoadObjects(); + $this->assertInstanceOf(EagerLoadedList::class, $eagerLoaded2); + } + } + } }