Skip to content

Commit e409261

Browse files
committed
Updated has query to property nest where statements, based on scope logic
1 parent 52d7c2a commit e409261

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

src/Illuminate/Database/Eloquent/Builder.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ public function has($relation, $operator = '>=', $count = 1, $boolean = 'and', C
822822
$query = $relation->{$queryType}($relation->getRelated()->newQuery(), $this);
823823

824824
if ($callback) {
825-
call_user_func($callback, $query);
825+
$this->applyCallback($callback, [$query], $query->getQuery());
826826
}
827827

828828
return $this->addHasWhere(
@@ -1137,14 +1137,27 @@ protected function callScope($scope, $parameters)
11371137
{
11381138
array_unshift($parameters, $this);
11391139

1140-
$query = $this->getQuery();
1140+
return $this->applyCallback([$this->model, $scope], $parameters);
1141+
}
1142+
1143+
/**
1144+
* Apply the given callback to a supplied (or the current) builder instance.
1145+
*
1146+
* @param callable $callback
1147+
* @param array $parameters
1148+
* @param \Illuminate\Database\Query\Builder $query
1149+
* @return mixed
1150+
*/
1151+
protected function applyCallback(callable $callback, $parameters = [], $query = null)
1152+
{
1153+
$query = $query ?: $this->getQuery();
11411154

11421155
// We will keep track of how many wheres are on the query before running the
11431156
// scope so that we can properly group the added scope constraints in the
11441157
// query as their own isolated nested where statement and avoid issues.
11451158
$originalWhereCount = count($query->wheres);
11461159

1147-
$result = call_user_func_array([$this->model, $scope], $parameters) ?: $this;
1160+
$result = call_user_func_array($callback, $parameters) ?: $this;
11481161

11491162
if ($this->shouldNestWheresForScope($query, $originalWhereCount)) {
11501163
$this->nestWheresForScope($query, $originalWhereCount);
@@ -1239,7 +1252,7 @@ protected function nestWheresForScope(QueryBuilder $query, $whereCounts)
12391252
// collection (0 and total where count) while also flattening the array
12401253
// and extracting unique values, ensuring that all wheres are sliced.
12411254
$whereOffsets = collect([0, $whereCounts, count($allWheres)])
1242-
->flatten()->unique();
1255+
->flatten()->unique();
12431256

12441257
$sliceFrom = $whereOffsets->shift();
12451258

tests/Database/DatabaseEloquentBuilderTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,21 @@ public function testHasWithContraintsAndHavingInSubquery()
526526
$this->assertEquals(['baz', 'qux', 'quuux'], $builder->getBindings());
527527
}
528528

529+
public function testHasWithContraintsWithOrWhereAndHavingInSubquery()
530+
{
531+
$model = new EloquentBuilderTestModelParentStub;
532+
533+
$builder = $model->where('name', 'larry');
534+
$builder->whereHas('address', function ($q) {
535+
$q->where('zipcode', '90210');
536+
$q->orWhere('zipcode', '90220');
537+
$q->having('street', '=', 'fooside dr');
538+
})->where('age', 29);
539+
540+
$this->assertEquals('select * from "eloquent_builder_test_model_parent_stubs" where "name" = ? and exists (select * from "eloquent_builder_test_model_close_related_stubs" where "eloquent_builder_test_model_parent_stubs"."foo_id" = "eloquent_builder_test_model_close_related_stubs"."id" and ("zipcode" = ? or "zipcode" = ?) having "street" = ?) and "age" = ?', $builder->toSql());
541+
$this->assertEquals(['larry', '90210', '90220', 'fooside dr', 29], $builder->getBindings());
542+
}
543+
529544
public function testHasWithContraintsAndJoinAndHavingInSubquery()
530545
{
531546
$model = new EloquentBuilderTestModelParentStub;
@@ -711,6 +726,11 @@ public function foo()
711726
return $this->belongsTo('EloquentBuilderTestModelCloseRelatedStub');
712727
}
713728

729+
public function address()
730+
{
731+
return $this->belongsTo('EloquentBuilderTestModelCloseRelatedStub', 'foo_id');
732+
}
733+
714734
public function activeFoo()
715735
{
716736
return $this->belongsTo('EloquentBuilderTestModelCloseRelatedStub', 'foo_id')->where('active', true);

0 commit comments

Comments
 (0)