Skip to content

Commit

Permalink
[10.x] Fixes on nesting operations performed while applying scopes. (#…
Browse files Browse the repository at this point in the history
…50207)

* Add tests to emphasize the issues with nesting due to scope (nesting "or" groups but not "or not" groups and doubling first where clause negation)

* Fix issues : also nest on "or not" clause, and don't repeat first where clause negation when nesting
  • Loading branch information
Guilhem-DELAITRE authored Feb 25, 2024
1 parent 8d47be3 commit 7af1994
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/Illuminate/Database/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -1454,9 +1454,9 @@ protected function groupWhereSliceForScope(QueryBuilder $query, $whereSlice)
// Here we'll check if the given subset of where clauses contains any "or"
// booleans and in this case create a nested where expression. That way
// we don't add any unnecessary nesting thus keeping the query clean.
if ($whereBooleans->contains('or')) {
if ($whereBooleans->contains(fn ($logicalOperator) => str_contains($logicalOperator, 'or'))) {
$query->wheres[] = $this->createNestedWhere(
$whereSlice, $whereBooleans->first()
$whereSlice, str_replace(' not', '', $whereBooleans->first())
);
} else {
$query->wheres = array_merge($query->wheres, $whereSlice);
Expand Down
26 changes: 26 additions & 0 deletions tests/Database/DatabaseEloquentLocalScopesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,32 @@ public function testLocalScopesCanChained()
$this->assertSame('select * from "table" where "active" = ? and "type" = ?', $query->toSql());
$this->assertEquals([true, 'foo'], $query->getBindings());
}

public function testLocalScopeNestingDoesntDoubleFirstWhereClauseNegation()
{
$model = new EloquentLocalScopesTestModel;
$query = $model
->newQuery()
->whereNot('firstWhere', true)
->orWhere('secondWhere', true)
->active();

$this->assertSame('select * from "table" where (not "firstWhere" = ? or "secondWhere" = ?) and "active" = ?', $query->toSql());
$this->assertEquals([true, true, true], $query->getBindings());
}

public function testLocalScopeNestingGroupsOrNotWhereClause()
{
$model = new EloquentLocalScopesTestModel;
$query = $model
->newQuery()
->where('firstWhere', true)
->orWhereNot('secondWhere', true)
->active();

$this->assertSame('select * from "table" where ("firstWhere" = ? or not "secondWhere" = ?) and "active" = ?', $query->toSql());
$this->assertEquals([true, true, true], $query->getBindings());
}
}

class EloquentLocalScopesTestModel extends Model
Expand Down

0 comments on commit 7af1994

Please sign in to comment.