Laravel8 Eloquent ANDとORの複合Whereの書き方

laravel

記事について

たまに頭がごっちゃになるwhereとorの結合について。慣れればクロージャを作っていくだけだけど、慣れるまではちょっと混乱するのかも?ちなみにコード例に書いているwhenは結果がtrueの場合のみクロージャの中を通る。今回は変数に値が入っている場合のみクエリーが生成される。

その1 (a OR b) AND (c OR d) の形式

本の(title か descriptionにkeyword1が含まれる) かつ (title か descriptionにkeyword2が含まれる)場合。つまり、titleとdescriptionにkeyword1とkeyword2両方が含まれる場合。

        $keyword1 = 'aaa';
        $keyword2 = 'bbb';
        $book = Book::select('books.*')
        ->when($keyword1, function($query) use ($keyword1) {
            $query->where(function($query) use($keyword1) {
                $query->orWhere("title", 'LIKE', '%'.$keyword1.'%');
                $query->orWhere("description", 'LIKE', '%'.$keyword1.'%');
            });
        })
        ->when($keyword2, function($query) use ($keyword2) {
            $query->where(function($query) use($keyword2) {
                $query->orWhere("title", 'LIKE', '%'.$keyword2.'%');
                $query->orWhere("description", 'LIKE', '%'.$keyword2.'%');
            });
        })
        ->get();

この時発行されるSQLは以下。

select `books`.*
from `books`
where (`title` LIKE '%aaa%' or `description` LIKE '%aaa%')
and (`title` LIKE '%bbb%' or `description` LIKE '%bbb%')

その2 (a AND b) OR (c AND d) の形式

本の(title と descriptionにkeyword1が含まれる) または (title と descriptionにkeyword2が含まれる)場合。つまり、titleとdescription両方にkeyword1かkeyword2が入っている場合。

        $book = Book::select('books.*')
        ->when($keyword1, function($query) use ($keyword1) {
            $query->orWhere(function($query) use($keyword1) {
                $query->where("title", 'LIKE', '%'.$keyword1.'%');
                $query->where("description", 'LIKE', '%'.$keyword1.'%');
            });
        })
        ->when($keyword2, function($query) use ($keyword2) {
            $query->orWhere(function($query) use($keyword2) {
                $query->where("title", 'LIKE', '%'.$keyword2.'%');
                $query->where("description", 'LIKE', '%'.$keyword2.'%');
            });
        })
        ->get();

この時発行されるSQLは以下。

select `books`.*
from `books`
where (`title` LIKE '%aaa%' and `description` LIKE '%aaa%')
or (`title` LIKE '%bbb%' and `description` LIKE '%bbb%')

番外編 ((a AND b) OR (c AND d)) AND e の形式

その2の形式をさらにANDでつなぎたい場合。ここでは仮に有効フラグ(enabled)を複合条件として入れている。

        $keyword1 = 'aaa';
        $keyword2 = 'bbb';
        $book = book::select('books.*')
        ->where(function($query) use($keyword1, $keyword2) {
            $query->when($keyword1, function($query) use ($keyword1) {
                $query->orWhere(function($query) use($keyword1) {
                    $query->where("title", 'LIKE', '%'.$keyword1.'%');
                    $query->where("description", 'LIKE', '%'.$keyword1.'%');
                });
            })
            ->when($keyword2, function($query) use ($keyword2) {
                $query->orWhere(function($query) use($keyword2) {
                    $query->where("title", 'LIKE', '%'.$keyword2.'%');
                    $query->where("description", 'LIKE', '%'.$keyword2.'%');
                });
            });
        })
        ->where('enabled', 1)
        ->get();

この時発行されるSQLは以下。

select `books`.* from `books`
where (
    (`title` LIKE '%aaa%' and `description` LIKE '%aaa%')
    or (`title` LIKE '%bbb%' and `description` LIKE '%bbb%')
)
and `enabled` = 1

余談

whereBetweenとかwhereInとかは条件が後ろにつくのにORだけorWhereなのはきっと理由があるのかな・・

コメント

タイトルとURLをコピーしました