From 6f3853f6666fcfa9284a18c2e64b0999f6ea47d8 Mon Sep 17 00:00:00 2001 From: Samoht70 Date: Sun, 26 Oct 2025 22:36:11 +0100 Subject: [PATCH 1/2] Fix eager loading relation for search operation --- src/Http/Response.php | 2 +- ...chIncludingRelationshipsOperationsTest.php | 66 +++++++++++++++++++ tests/Support/Models/HasManyRelation.php | 5 ++ tests/Support/Models/Model.php | 6 ++ .../Rest/Resources/HasManyResource.php | 14 +++- .../Rest/Resources/HasManyThroughResource.php | 5 +- .../Support/Rest/Resources/ModelResource.php | 1 + 7 files changed, 96 insertions(+), 3 deletions(-) diff --git a/src/Http/Response.php b/src/Http/Response.php index 97a19b6..9b167b0 100644 --- a/src/Http/Response.php +++ b/src/Http/Response.php @@ -81,7 +81,7 @@ public function modelToResponse(Model $model, Resource $resource, array $request $currentRequestArray = $relation === null ? $requestArray : collect($requestArray['includes'] ?? []) ->first(function ($include) use ($relation) { return preg_match('/(?:\.\b)?'.$relation->relation.'\b/', $include['relation']); - }); + }) ?? []; return array_merge( // toArray to take advantage of Laravel's logic diff --git a/tests/Feature/Controllers/SearchIncludingRelationshipsOperationsTest.php b/tests/Feature/Controllers/SearchIncludingRelationshipsOperationsTest.php index 890aadc..f962a67 100644 --- a/tests/Feature/Controllers/SearchIncludingRelationshipsOperationsTest.php +++ b/tests/Feature/Controllers/SearchIncludingRelationshipsOperationsTest.php @@ -10,6 +10,7 @@ use Lomkit\Rest\Tests\Support\Database\Factories\BelongsToManyRelationFactory; use Lomkit\Rest\Tests\Support\Database\Factories\BelongsToRelationFactory; use Lomkit\Rest\Tests\Support\Database\Factories\HasManyRelationFactory; +use Lomkit\Rest\Tests\Support\Database\Factories\HasManyThroughRelationFactory; use Lomkit\Rest\Tests\Support\Database\Factories\HasOneOfManyRelationFactory; use Lomkit\Rest\Tests\Support\Database\Factories\HasOneRelationFactory; use Lomkit\Rest\Tests\Support\Database\Factories\ModelFactory; @@ -17,6 +18,7 @@ use Lomkit\Rest\Tests\Support\Models\BelongsToManyRelation; use Lomkit\Rest\Tests\Support\Models\BelongsToRelation; use Lomkit\Rest\Tests\Support\Models\HasManyRelation; +use Lomkit\Rest\Tests\Support\Models\HasManyThroughRelation; use Lomkit\Rest\Tests\Support\Models\HasOneOfManyRelation; use Lomkit\Rest\Tests\Support\Models\HasOneRelation; use Lomkit\Rest\Tests\Support\Models\Model; @@ -25,6 +27,7 @@ use Lomkit\Rest\Tests\Support\Rest\Resources\BelongsToManyResource; use Lomkit\Rest\Tests\Support\Rest\Resources\BelongsToResource; use Lomkit\Rest\Tests\Support\Rest\Resources\HasManyResource; +use Lomkit\Rest\Tests\Support\Rest\Resources\HasManyThroughResource; use Lomkit\Rest\Tests\Support\Rest\Resources\HasOneOfManyResource; use Lomkit\Rest\Tests\Support\Rest\Resources\HasOneResource; use Lomkit\Rest\Tests\Support\Rest\Resources\ModelResource; @@ -578,6 +581,69 @@ public function test_getting_a_list_of_resources_including_has_many_relation(): ); } + public function test_getting_a_list_of_resources_including_has_many_relation_with_loaded_relations_in_model(): void + { + $matchingModel = ModelFactory::new() + ->createOne()->fresh(); + + $hasMany = HasManyRelationFactory::new() + ->for($matchingModel) + ->createOne(); + + HasManyThroughRelationFactory::new() + ->for($hasMany) + ->createOne(); + + Gate::policy(Model::class, GreenPolicy::class); + Gate::policy(HasManyRelation::class, GreenPolicy::class); + Gate::policy(HasManyThroughRelation::class, GreenPolicy::class); + + $response = $this->post( + '/api/models/search', + [ + 'search' => [ + 'includes' => [ + [ + 'relation' => 'hasManyRelationWithEagerLoadingRelation', + ], + ], + ], + ], + ['Accept' => 'application/json'] + ); + + $this->assertResourcePaginated( + $response, + [$matchingModel], + new ModelResource(), + [ + [ + 'has_many_relation_with_eager_loading_relation' => $matchingModel->hasManyRelationWithEagerLoadingRelation() + ->orderBy('id') + ->get() + ->map(function ($relation) { + $relation->has_many_through_relation = $relation->hasManyThroughRelation + ->map(function ($relation) { + $relation->has_many_relation = $relation->hasManyRelation->only( + (new HasManyResource())->getFields(app()->make(RestRequest::class)) + ); + + return $relation->only(array_merge( + (new HasManyThroughResource())->getFields(app()->make(RestRequest::class)), + ['has_many_relation'] + )); + })->toArray(); + + return $relation->only(array_merge( + (new HasManyResource())->getFields(app()->make(RestRequest::class)), + ['has_many_through_relation'] + )); + })->toArray(), + ], + ] + ); + } + public function test_getting_a_list_of_resources_including_belongs_to_many_relation(): void { $matchingModel = ModelFactory::new() diff --git a/tests/Support/Models/HasManyRelation.php b/tests/Support/Models/HasManyRelation.php index 9e40ac4..f4a02f4 100644 --- a/tests/Support/Models/HasManyRelation.php +++ b/tests/Support/Models/HasManyRelation.php @@ -10,4 +10,9 @@ public function model() { return $this->belongsTo(\Lomkit\Rest\Tests\Support\Models\Model::class); } + + public function hasManyThroughRelation() + { + return $this->hasMany(HasManyThroughRelation::class, 'has_many_relation_id'); + } } diff --git a/tests/Support/Models/Model.php b/tests/Support/Models/Model.php index d5e47bb..6bcee8b 100644 --- a/tests/Support/Models/Model.php +++ b/tests/Support/Models/Model.php @@ -47,6 +47,12 @@ public function hasManyRelation() return $this->hasMany(HasManyRelation::class, 'model_id'); } + public function hasManyRelationWithEagerLoadingRelation() + { + return $this->hasMany(HasManyRelation::class, 'model_id') + ->with('hasManyThroughRelation.hasManyRelation'); + } + public function hasOneOfManyRelation() { return $this->hasOne(HasOneOfManyRelation::class, 'model_id')->ofMany(); diff --git a/tests/Support/Rest/Resources/HasManyResource.php b/tests/Support/Rest/Resources/HasManyResource.php index 5275ebf..189e080 100644 --- a/tests/Support/Rest/Resources/HasManyResource.php +++ b/tests/Support/Rest/Resources/HasManyResource.php @@ -5,6 +5,8 @@ use Lomkit\Rest\Concerns\Resource\DisableGates; use Lomkit\Rest\Http\Requests\RestRequest; use Lomkit\Rest\Http\Resource; +use Lomkit\Rest\Relations\BelongsTo; +use Lomkit\Rest\Relations\HasMany; use Lomkit\Rest\Tests\Support\Models\HasManyRelation; class HasManyResource extends Resource @@ -14,7 +16,10 @@ class HasManyResource extends Resource public function relations(RestRequest $request): array { - return []; + return [ + BelongsTo::make('model', ModelResource::class), + HasMany::make('hasManyThroughRelation', HasManyThroughResource::class), + ]; } public function fields(RestRequest $request): array @@ -24,4 +29,11 @@ public function fields(RestRequest $request): array 'number', ]; } + + public function defaultOrderBy(RestRequest $request): array + { + return [ + 'id' => 'asc', + ]; + } } diff --git a/tests/Support/Rest/Resources/HasManyThroughResource.php b/tests/Support/Rest/Resources/HasManyThroughResource.php index 894fe37..7e245bb 100644 --- a/tests/Support/Rest/Resources/HasManyThroughResource.php +++ b/tests/Support/Rest/Resources/HasManyThroughResource.php @@ -5,6 +5,7 @@ use Lomkit\Rest\Concerns\Resource\DisableGates; use Lomkit\Rest\Http\Requests\RestRequest; use Lomkit\Rest\Http\Resource; +use Lomkit\Rest\Relations\BelongsTo; use Lomkit\Rest\Tests\Support\Models\HasManyThroughRelation; class HasManyThroughResource extends Resource @@ -14,7 +15,9 @@ class HasManyThroughResource extends Resource public function relations(RestRequest $request): array { - return []; + return [ + BelongsTo::make('hasManyRelation', HasManyResource::class) + ]; } public function fields(RestRequest $request): array diff --git a/tests/Support/Rest/Resources/ModelResource.php b/tests/Support/Rest/Resources/ModelResource.php index 9052e2c..f962111 100644 --- a/tests/Support/Rest/Resources/ModelResource.php +++ b/tests/Support/Rest/Resources/ModelResource.php @@ -53,6 +53,7 @@ public function relations(RestRequest $request): array HasOneOfMany::make('hasOneOfManyRelation', HasOneOfManyResource::class), BelongsTo::make('belongsToRelation', BelongsToResource::class), HasMany::make('hasManyRelation', HasManyResource::class), + HasMany::make('hasManyRelationWithEagerLoadingRelation', HasManyResource::class), BelongsToMany::make('belongsToManyRelation', BelongsToManyResource::class) ->withPivotRules([ 'number' => 'numeric', From 63b6adc665888ea737ade32eb89033a293b9bc66 Mon Sep 17 00:00:00 2001 From: Samoht70 Date: Sun, 26 Oct 2025 22:44:28 +0100 Subject: [PATCH 2/2] Fix CI --- .../Controllers/SearchIncludingRelationshipsOperationsTest.php | 2 +- tests/Support/Rest/Resources/HasManyThroughResource.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Feature/Controllers/SearchIncludingRelationshipsOperationsTest.php b/tests/Feature/Controllers/SearchIncludingRelationshipsOperationsTest.php index f962a67..17c6c09 100644 --- a/tests/Feature/Controllers/SearchIncludingRelationshipsOperationsTest.php +++ b/tests/Feature/Controllers/SearchIncludingRelationshipsOperationsTest.php @@ -581,7 +581,7 @@ public function test_getting_a_list_of_resources_including_has_many_relation(): ); } - public function test_getting_a_list_of_resources_including_has_many_relation_with_loaded_relations_in_model(): void + public function test_getting_a_list_of_resources_including_has_many_relation_with_eager_loading_relations(): void { $matchingModel = ModelFactory::new() ->createOne()->fresh(); diff --git a/tests/Support/Rest/Resources/HasManyThroughResource.php b/tests/Support/Rest/Resources/HasManyThroughResource.php index 7e245bb..895c891 100644 --- a/tests/Support/Rest/Resources/HasManyThroughResource.php +++ b/tests/Support/Rest/Resources/HasManyThroughResource.php @@ -16,7 +16,7 @@ class HasManyThroughResource extends Resource public function relations(RestRequest $request): array { return [ - BelongsTo::make('hasManyRelation', HasManyResource::class) + BelongsTo::make('hasManyRelation', HasManyResource::class), ]; }