laravel/framework

orWhere generating an OR when it previously would generate an AND

Open

#53,628 opened on Nov 22, 2024

View on GitHub
 (13 comments) (9 reactions) (0 assignees)PHP (34,705 stars) (11,882 forks)batch import
help wanted

Description

Laravel Version

11.33.2

PHP Version

8.3.13

Database Driver & Version

MySQL

Description

I recently upgraded a legacy laravel application from 5.4 to laravel 11.

The following code:

$booking_boats = $this->current_location->booking_boats()
    ->with(['booking'])
    ->where(function ($query) {
        $query->where('booking_boats.status','Queued')
                ->orWhere([
                    ['booking_boats.status','=','On Water'],
                    ['booking_boats.checkout_date','!=',''],
                ]);
    })
    ->get();

Would previously generate a query like this:

SELECT  *
FROM `booking_boats`
INNER JOIN `bookings`
ON `bookings`.`id` = `booking_boats`.`booking_id`
WHERE `bookings`.`deleted_at` is null
AND `bookings`.`location_id` = ?
AND (`booking_boats`.`status` = ? or (`booking_boats`.`status` = ? AND `booking_boats`.`checkout_date` != ?))
AND `booking_boats`.`deleted_at` is null

The important part is: (booking_boats.status = ? AND booking_boats.checkout_date != ?)

In Laravel 11, the following query is generated:

SELECT  *
FROM `booking_boats`
INNER JOIN `bookings`
ON `bookings`.`id` = `booking_boats`.`booking_id`
WHERE `bookings`.`location_id` = ?
AND (`booking_boats`.`status` = ? or (`booking_boats`.`status` = ? or `booking_boats`.`checkout_date` != ?))
AND `booking_boats`.`deleted_at` is null
AND `bookings`.`deleted_at` is null

The important part is: (booking_boats.status = ? or booking_boats.checkout_date != ?)

So, previously using ->orWhere with an array syntax would generate an AND query, but now it generates an OR query.

This seems like a bug but if somehow I missed this in the laravel upgrade notes I would appreciate knowing what exactly was changed and what functions are impacted as there are hundreds of queries I will have to update.

Thank you.

Steps To Reproduce

Perform an ->orWhere using multiple array elements, ie:

 $query->where('booking_boats.status','Queued')
    ->orWhere([
        ['booking_boats.status','=','On Water'],
        ['booking_boats.checkout_date','!=',''],
]);

Contributor guide