From 5694e1dc33f40b803f0e1d608c195298ebcb2625 Mon Sep 17 00:00:00 2001 From: Erik Gaal Date: Wed, 30 Mar 2022 17:13:58 +0200 Subject: [PATCH] [9.x] Make `whereBelongsTo` accept Collection (#41733) * Add whereBelongsToOneOf clause * Refactor into whereBelongsTo method * throw exception on empty Co-authored-by: Taylor Otwell --- .../Concerns/QueriesRelationships.php | 21 +++++++++++--- .../Database/DatabaseEloquentBuilderTest.php | 28 +++++++++++++++++-- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php index 8b6f9b4ec3ab..bbb6f926c5a5 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php @@ -5,6 +5,7 @@ use BadMethodCallException; use Closure; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\RelationNotFoundException; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\MorphTo; @@ -12,6 +13,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Database\Query\Expression; use Illuminate\Support\Str; +use InvalidArgumentException; trait QueriesRelationships { @@ -461,7 +463,7 @@ public function orWhereMorphedTo($relation, $model) /** * Add a "belongs to" relationship where clause to the query. * - * @param \Illuminate\Database\Eloquent\Model $related + * @param \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection<\Illuminate\Database\Eloquent\Model> $related * @param string|null $relationshipName * @param string $boolean * @return $this @@ -470,6 +472,18 @@ public function orWhereMorphedTo($relation, $model) */ public function whereBelongsTo($related, $relationshipName = null, $boolean = 'and') { + if (! $related instanceof Collection) { + $relatedCollection = $related->newCollection([$related]); + } else { + $relatedCollection = $related; + + $related = $relatedCollection->first(); + } + + if ($relatedCollection->isEmpty()) { + throw new InvalidArgumentException("Collection given to whereBelongsTo method may not be empty."); + } + if ($relationshipName === null) { $relationshipName = Str::camel(class_basename($related)); } @@ -484,10 +498,9 @@ public function whereBelongsTo($related, $relationshipName = null, $boolean = 'a throw RelationNotFoundException::make($this->model, $relationshipName, BelongsTo::class); } - $this->where( + $this->whereIn( $relationship->getQualifiedForeignKeyName(), - '=', - $related->getAttributeValue($relationship->getOwnerKeyName()), + $relatedCollection->pluck($relationship->getOwnerKeyName())->toArray(), $boolean, ); diff --git a/tests/Database/DatabaseEloquentBuilderTest.php b/tests/Database/DatabaseEloquentBuilderTest.php index c22010595d93..8873b0310a3e 100755 --- a/tests/Database/DatabaseEloquentBuilderTest.php +++ b/tests/Database/DatabaseEloquentBuilderTest.php @@ -1041,7 +1041,7 @@ public function testWhereBelongsTo() $builder = $this->getBuilder(); $builder->shouldReceive('from')->with('eloquent_builder_test_where_belongs_to_stubs'); $builder->setModel($related); - $builder->getQuery()->shouldReceive('where')->once()->with('eloquent_builder_test_where_belongs_to_stubs.parent_id', '=', 2, 'and'); + $builder->getQuery()->shouldReceive('whereIn')->once()->with('eloquent_builder_test_where_belongs_to_stubs.parent_id', [2], 'and'); $result = $builder->whereBelongsTo($parent); $this->assertEquals($result, $builder); @@ -1049,10 +1049,34 @@ public function testWhereBelongsTo() $builder = $this->getBuilder(); $builder->shouldReceive('from')->with('eloquent_builder_test_where_belongs_to_stubs'); $builder->setModel($related); - $builder->getQuery()->shouldReceive('where')->once()->with('eloquent_builder_test_where_belongs_to_stubs.parent_id', '=', 2, 'and'); + $builder->getQuery()->shouldReceive('whereIn')->once()->with('eloquent_builder_test_where_belongs_to_stubs.parent_id', [2], 'and'); $result = $builder->whereBelongsTo($parent, 'parent'); $this->assertEquals($result, $builder); + + $parents = new Collection([new EloquentBuilderTestWhereBelongsToStub([ + 'id' => 2, + 'parent_id' => 1, + ]), new EloquentBuilderTestWhereBelongsToStub([ + 'id' => 3, + 'parent_id' => 1, + ])]); + + $builder = $this->getBuilder(); + $builder->shouldReceive('from')->with('eloquent_builder_test_where_belongs_to_stubs'); + $builder->setModel($related); + $builder->getQuery()->shouldReceive('whereIn')->once()->with('eloquent_builder_test_where_belongs_to_stubs.parent_id', [2, 3], 'and'); + + $result = $builder->whereBelongsTo($parents); + $this->assertEquals($result, $builder); + + $builder = $this->getBuilder(); + $builder->shouldReceive('from')->with('eloquent_builder_test_where_belongs_to_stubs'); + $builder->setModel($related); + $builder->getQuery()->shouldReceive('whereIn')->once()->with('eloquent_builder_test_where_belongs_to_stubs.parent_id', [2, 3], 'and'); + + $result = $builder->whereBelongsTo($parents, 'parent'); + $this->assertEquals($result, $builder); } public function testDeleteOverride()