はじめに
Laravel の Eloquent を使ってデータを検索する際、orWhere
を適切に使用しないと、意図しない検索結果を取得していた書き方になっていたので備忘録として残します。
例
以下の場合
$query = User::where('age', 30)
->where('gender', 'male')
->orWhere('status', 'active')
->get();
-
age
が30
かつgender
がmale
またはstatus
がactive
という条件でユーザーを取得する。実際に生成されるSQLは以下のようになる。
SELECT * FROM users
WHERE age = 30
AND gender = 'male'
OR status = 'active'
-
age = 30 AND gender = 'male'
の条件が優先されず、 -
status = 'active'
だけを満たすユーザーも取得される。
対応: 条件のグループ化
上記の問題を解決するために、Eloquent の where
メソッドに クロージャ(無名関数) を使用して条件をグループ化する。
$query = User::where(function ($q) {
$q->where('age', 30)
->where('gender', 'male');
})
->orWhere('status', 'active')
->get();
SQLは次のようになる
SELECT * FROM users
WHERE (age = 30 AND gender = 'male')
OR status = 'active'
括弧が適切に適用され、期待通りの条件評価される。
まとめ
Laravelの Eloquentは便利だけど、使い方を間違えると意図しないデータを取得してしまうので注意が必要。生のSQL書いて、Eloquentに書くようにしている。