Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Multiple WHERE() Operator Precedence

I have the following query written using Eloquent:

Contact::select(DB::raw("DATE_FORMAT(DATE(`created_at`),'%b %d') as date"))
                                 ->addSelect(DB::raw("`created_at`"))
                                 ->addSelect(DB::raw("COUNT(*) as `count`"))
                                 ->where('created_at', '>', $date)
                                 ->ofType($type)
                                 ->groupBy('date')
                                 ->orderBy('created_at', 'ASC')
                                 ->lists('count', 'date');

You can see it uses a query scope method ofType() Here is that method, it just adds a bunch of extra where clauses to the query:

return $query->where('list_name', '=', 'Apples')
            ->orWhere('list_name', '=', 'Oranges')
            ->orWhere('list_name', '=', 'Pears')
            ->orWhere('list_name', '=', 'Plums')
            ->orWhere('list_name', '=', 'Blueberries');

Ultimately this results in the following real SQL query:

SELECT DATE_FORMAT(DATE(`created_at`),'%b %d') as date,`created_at`, COUNT(*) as `count` 
FROM `contacts` 
WHERE `created_at` > '2014-10-02 00:00:00' 
AND `list_name` = 'Apples' 
OR `list_name` = 'Oranges' 
OR `list_name` = 'Pears' 
OR `list_name` = 'Plums' 
OR `list_name` = 'Blueberries' 
GROUP BY `date` 
ORDER BY `created_at` ASC

The problem is, the WHERE created_at > '2014-10-02 00:00:00' clause is being missed when the OR clauses kick in. Due to operator precendence. I need to wrap all the clauses after the first AND in parentheses, like so:

 SELECT DATE_FORMAT(DATE(`created_at`),'%b %d') as date,`created_at`, COUNT(*) as `count` 
    FROM `contacts` 
    WHERE `created_at` > '2014-10-02 00:00:00' 
    AND 
   (`list_name` = 'Apples' 
    OR `list_name` = 'Oranges' 
    OR `list_name` = 'Pears' 
    OR `list_name` = 'Plums' 
    OR `list_name` = 'Blueberries')
    GROUP BY `date` 
    ORDER BY `created_at` ASC

So, my question is, how would I achieve this using the eloquent query builder. Thank you.

like image 632
Chris J Allen Avatar asked Oct 08 '14 10:10

Chris J Allen


People also ask

How to use multiple conditions in where clause in Laravel?

Laravel multiple where conditions - [OR]: In case you want your clauses to be joined with OR rather than AND , you could use the orWhere method: Syntax: ... ->where('column','operator','value') ->orWhere('column','operator','value') ...

Can I use two where in Laravel?

Multiple Where Condition with Query BuilderIf you want to write multiple where clause, then you can go with the laravel query builder method.

How to use with and where in Laravel?

you can simple use orWhere eloquent method in laravel 6, laravel 7, laravel 8 and laravel 9. If you need to use sql or where query in laravel then you can use it. Laravel provide orWhere() to use sql or query query. in or where() we just need to pass two argument one is column name and will be value.


1 Answers

Thanks to mOrsa I've figured it out, by changing my query scope method to take advantage of advanced where:

return $query->where(function($query){

          $query->orWhere('list_name', '=', 'Apples')
                ->orWhere('list_name', '=', 'Oranges')
                ->orWhere('list_name', '=', 'Pears')
                ->orWhere('list_name', '=', 'Plums')
                ->orWhere('list_name', '=', 'Blueberries');
        });

I get the desired SQL.

like image 175
Chris J Allen Avatar answered Sep 28 '22 00:09

Chris J Allen