From 056217d6f9e057d0bf56efaaac445c7c7f14b1d1 Mon Sep 17 00:00:00 2001 From: yousef kadah Date: Thu, 23 Oct 2025 15:19:05 +0300 Subject: [PATCH] [12.x] Fix orWhere() with array syntax to join conditions with AND MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a regression where `orWhere()` with array syntax was incorrectly joining multiple array conditions with OR instead of AND, breaking backward compatibility from Laravel 5.4+. **Problem:** ```php ->where('status', 'Queued') ->orWhere([ ['status', '=', 'On Water'], ['checkout_date', '!=', ''] ]) ``` Previously generated (correct): ```sql WHERE status = ? OR (status = ? AND checkout_date != ?) ``` After regression, generated (incorrect): ```sql WHERE status = ? OR (status = ? OR checkout_date != ?) ``` **Root Cause:** The `addArrayOfWheres()` method was passing the `$boolean` parameter ('or') to each individual condition inside the array, when it should only control how the entire group connects to previous clauses. **Solution:** Array items are now always joined with AND (the natural behavior of "where"), while the `$boolean` parameter only controls how the nested group connects to the rest of the query. Fixes #53628 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/Illuminate/Database/Query/Builder.php | 6 +++--- tests/Database/DatabaseQueryBuilderTest.php | 24 ++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index 03195c5b9f4f..cd9bb240d3d3 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -927,12 +927,12 @@ public function where($column, $operator = null, $value = null, $boolean = 'and' */ protected function addArrayOfWheres($column, $boolean, $method = 'where') { - return $this->whereNested(function ($query) use ($column, $method, $boolean) { + return $this->whereNested(function ($query) use ($column, $method) { foreach ($column as $key => $value) { if (is_numeric($key) && is_array($value)) { - $query->{$method}(...array_values($value), boolean: $boolean); + $query->{$method}(...array_values($value)); } else { - $query->{$method}($key, '=', $value, $boolean); + $query->{$method}($key, '=', $value); } } }, $boolean); diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index 53629cdff191..8e6b64d7f37c 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -2594,8 +2594,8 @@ public function testOrWheresHaveConsistentResults() $queries[] = $builder->toSql(); $this->assertSame([ - 'select * from "users" where "xxxx" = ? or ("foo" = ? or "bar" = ?)', - 'select * from "users" where "xxxx" = ? or ("foo" = ? or "bar" = ?)', + 'select * from "users" where "xxxx" = ? or ("foo" = ? and "bar" = ?)', + 'select * from "users" where "xxxx" = ? or ("foo" = ? and "bar" = ?)', ], $queries); $queries = []; @@ -2608,8 +2608,8 @@ public function testOrWheresHaveConsistentResults() $queries[] = $builder->toSql(); $this->assertSame([ - 'select * from "users" where "xxxx" = ? or ("foo" = "_foo" or "bar" = "_bar")', - 'select * from "users" where "xxxx" = ? or ("foo" = "_foo" or "bar" = "_bar")', + 'select * from "users" where "xxxx" = ? or ("foo" = "_foo" and "bar" = "_bar")', + 'select * from "users" where "xxxx" = ? or ("foo" = "_foo" and "bar" = "_bar")', ], $queries); } @@ -2802,50 +2802,50 @@ public function testWhereWithArrayConditions() $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('xxxx', 'xxxx')->orWhere([['foo', 1], ['bar', 2]]); - $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = ? or "bar" = ?)', $builder->toSql()); + $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = ? and "bar" = ?)', $builder->toSql()); $this->assertEquals([0 => 'xxxx', 1 => 1, 2 => 2], $builder->getBindings()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('xxxx', 'xxxx')->orWhere(['foo' => 1, 'bar' => 2]); - $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = ? or "bar" = ?)', $builder->toSql()); + $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = ? and "bar" = ?)', $builder->toSql()); $this->assertEquals([0 => 'xxxx', 1 => 1, 2 => 2], $builder->getBindings()); // where()->orWhere(key, <, value) $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('xxxx', 'xxxx')->orWhere([['foo', 1], ['bar', '<', 2]]); - $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = ? or "bar" < ?)', $builder->toSql()); + $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = ? and "bar" < ?)', $builder->toSql()); $this->assertEquals([0 => 'xxxx', 1 => 1, 2 => 2], $builder->getBindings()); // where()->orWhereColumn(col1, col2) $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('xxxx', 'xxxx')->orWhereColumn([['foo', '_foo'], ['bar', '_bar']]); - $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = "_foo" or "bar" = "_bar")', $builder->toSql()); + $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = "_foo" and "bar" = "_bar")', $builder->toSql()); $this->assertEquals([0 => 'xxxx'], $builder->getBindings()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('xxxx', 'xxxx')->orWhereColumn(['foo' => '_foo', 'bar' => '_bar']); - $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = "_foo" or "bar" = "_bar")', $builder->toSql()); + $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = "_foo" and "bar" = "_bar")', $builder->toSql()); $this->assertEquals([0 => 'xxxx'], $builder->getBindings()); // where()->orWhere(key, <, value) $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('xxxx', 'xxxx')->orWhere([['foo', 1], ['bar', '<', 2]]); - $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = ? or "bar" < ?)', $builder->toSql()); + $this->assertSame('select * from "users" where "xxxx" = ? or ("foo" = ? and "bar" < ?)', $builder->toSql()); $this->assertEquals([0 => 'xxxx', 1 => 1, 2 => 2], $builder->getBindings()); // where()->orWhereNot(key, value) $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('xxxx', 'xxxx')->orWhereNot([['foo', 1], ['bar', 2]]); - $this->assertSame('select * from "users" where "xxxx" = ? or not (("foo" = ? or "bar" = ?))', $builder->toSql()); + $this->assertSame('select * from "users" where "xxxx" = ? or not (("foo" = ? and "bar" = ?))', $builder->toSql()); $this->assertEquals([0 => 'xxxx', 1 => 1, 2 => 2], $builder->getBindings()); $builder = $this->getBuilder(); $builder->select('*')->from('users')->where('xxxx', 'xxxx')->orWhereNot(['foo' => 1, 'bar' => 2]); - $this->assertSame('select * from "users" where "xxxx" = ? or not (("foo" = ? or "bar" = ?))', $builder->toSql()); + $this->assertSame('select * from "users" where "xxxx" = ? or not (("foo" = ? and "bar" = ?))', $builder->toSql()); $this->assertEquals([0 => 'xxxx', 1 => 1, 2 => 2], $builder->getBindings()); // where()->orWhereNot(key, <, value)