From e1abb4ac884bbc51a9a28ca3ccd409e3ccf595ca Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Fri, 6 Mar 2026 11:55:19 +0400 Subject: [PATCH] Support LoadOptions DTOs in BulkLoader::load() --- src/Relation/BulkLoader.php | 5 ++- src/Relation/RelationLoaderInterface.php | 7 ++-- tests/ORM/Unit/Relation/BulkLoaderTest.php | 49 ++++++++++++++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/Relation/BulkLoader.php b/src/Relation/BulkLoader.php index 8705bd37a..2138da444 100644 --- a/src/Relation/BulkLoader.php +++ b/src/Relation/BulkLoader.php @@ -8,6 +8,7 @@ use Cycle\ORM\ORMInterface; use Cycle\ORM\Reference\ReferenceInterface; use Cycle\ORM\SchemaInterface; +use Cycle\ORM\Select\Options\LoadOptions; use Cycle\ORM\Select\UpdateLoader; use Cycle\ORM\Service\EntityFactoryInterface; use Cycle\ORM\Service\SourceProviderInterface; @@ -34,7 +35,7 @@ public function collect(object ...$entities): RelationLoaderInterface { if ($entities === []) { return new class implements RelationLoaderInterface { - public function load(string $relation, array $options = []): static + public function load(string $relation, LoadOptions|array $options = []): static { return $this; } @@ -65,7 +66,7 @@ public function run(): void {} return $clone; } - public function load(string $relation, array $options = []): static + public function load(string $relation, LoadOptions|array $options = []): static { $this->loader->loadRelation($relation, $options, load: true); diff --git a/src/Relation/RelationLoaderInterface.php b/src/Relation/RelationLoaderInterface.php index c2b606d99..f6fb48958 100644 --- a/src/Relation/RelationLoaderInterface.php +++ b/src/Relation/RelationLoaderInterface.php @@ -5,6 +5,7 @@ namespace Cycle\ORM\Relation; use Cycle\ORM\Select; +use Cycle\ORM\Select\Options\LoadOptions; /** * Relations loader @@ -23,11 +24,11 @@ interface RelationLoaderInterface * Define relation to be loaded. * * @param non-empty-string $relation Relation name - * @param array $options Relation loading options + * @param LoadOptions|array $options Relation loading options * - * @see Select::load() for available options\ + * @see Select::load() for available options */ - public function load(string $relation, array $options = []): static; + public function load(string $relation, LoadOptions|array $options = []): static; /** * Execute relation loading for all collected entities. diff --git a/tests/ORM/Unit/Relation/BulkLoaderTest.php b/tests/ORM/Unit/Relation/BulkLoaderTest.php index 22e08b5e5..3bcdc3a9a 100644 --- a/tests/ORM/Unit/Relation/BulkLoaderTest.php +++ b/tests/ORM/Unit/Relation/BulkLoaderTest.php @@ -12,6 +12,8 @@ use Cycle\ORM\Relation\BulkLoader; use Cycle\ORM\Relation\RelationLoaderInterface; use Cycle\ORM\Schema; +use Cycle\ORM\Select\Options\HasOneLoadOptions; +use Cycle\ORM\Select\Options\LoadOptions; use Cycle\ORM\Tests\Fixtures\OneWayUuidTypecast; use Cycle\ORM\Tests\Fixtures\Profile; use Cycle\ORM\Tests\Fixtures\User; @@ -206,6 +208,53 @@ public function testLoadWithCustomOptions(): void $this->assertSame($loader, $result); } + /** + * Test load with LoadOptions DTO + */ + public function testLoadWithLoadOptionsDTO(): void + { + $orm = $this->createORM(); + + $entity = new User(); + $loader = new BulkLoader($orm); + $loader = $loader->collect($entity); + $result = $loader->load('profile', new LoadOptions()); + + $this->assertSame($loader, $result); + } + + /** + * Test load with HasOneLoadOptions DTO + */ + public function testLoadWithHasOneLoadOptionsDTO(): void + { + $orm = $this->createORM(); + + $entity = new User(); + $loader = new BulkLoader($orm); + $loader = $loader->collect($entity); + $result = $loader->load('profile', new HasOneLoadOptions( + where: ['id' => 1], + )); + + $this->assertSame($loader, $result); + } + + /** + * Test empty collect returns loader that accepts LoadOptions DTO + */ + public function testEmptyCollectLoadAcceptsLoadOptionsDTO(): void + { + $orm = $this->createORM(); + $loader = (new BulkLoader($orm))->collect(); + + self::assertInstanceOf(RelationLoaderInterface::class, $loader); + $result = $loader->load('profile', new HasOneLoadOptions()); + self::assertSame($loader, $result); + + $loader->run(); + } + /** * BulkLoader should handle Stringable PK values when typecast is one-directional. *