コンテンツにスキップ

Top

Laravel で model をつかって and と or が混じったwhere のクエリを作る方法

Laravel で model を使って クエリを作る際、 where で and、orWhere で or のwhere 句を作成することができる。

and のみ、or のみだとなんの問題もなく簡単なのだが、and と or が混ざるととたんに意図したsql文が作れなくなる。

たとえば、

select * from hoge where a = 'a' and (b = 'b' or c = 'c'); 
というSQL文を作りたい場合、日本語でいえばa が 'a'でかつ、bが'b'またはcが'c'のものを引っ張りたい。

それを単純にmodelでやると、

$ret = Hoge::where('a', 'a')->orWhere('b','b')->orWhere('c','c')->get();
としてしまいがち。
でもこれで生成されるSQL文は、
select * from hoge where a = 'a' and b = 'b' or c = 'c';
だ。orにカッコがないので条件がおかしくなっている。
日本語で言えば、aが'a'かつbが'b、又はcが'c'となってしまい意味が違う。

じゃぁどうしたらよいかというと、ちょっと見慣れない書き方が、

$model = new Hoge();
$model->where('a','a')->where(function($model) {
                                  $model->where('b', 'b');
                                  $model->orWhere('c', 'c');
                             });
のようにwhereの中にfunctionを書いて、その中でwhereとorWhereを書くときちんとカッコになってくれる。

model内で具体的にどんなSQL文が生成されたか確認したい場合は、

$model->toSql()
$model->getBindings()
などをLogなどで出力すれば見れる。

ちなみにだが、funtion内は外の変数はスコープ外で使えないので、function外の値を使いたい場合はuseを使う。

$x = 'x'; // これをfunction内で使いたい場合

$model = new Hoge();
$model->where('a','a')->where(function($model) use($x) {
                                  $model->where('b', 'b');
                                  $model->orWhere('c', $x);
                             });

のように、use を使って渡すようにする。

以上!