難しいクエリを作りたくない
whereHasは遅い。激遅い。
left joinや、whereInすれば良いらしいと推測。
でもleft joinはコーディングがしんどいのよな……。
結論:whereInで頑張れば簡単だし改善はできるよ
modelの関係性
usersはcommentsと「1対多」の関係。
whereHasを用いた場合
前提
- リレーション先のカラムでwhereしたい。
Commentsを基本とした場合
UsersController.php
// nameで検索したい
Comments::whereHas('Users', function($query) use ($name){
$query = $query->where('name', $name);
});
whereInに置き換え
Commentsを基本とした場合
UsersController.php
// nameで検索したい
$comments = Comments::whereIn('user_id', function($query) use($name)
{
$query->from('users')
->select('users.id')
->where('users.name', $name);
});
なんだか冗長で見辛い。どうせサブクエリだし2回叩けばいいんじゃね?
最適解
whereInに置き換えつつ、クエリを2回叩く
Commentsを基本とした場合
UsersController.php
// nameで検索したい
// users単体で、クエリをたたく
$users = User::select('id')
->where('name', $name);
// その結果を、当モデルに組み込む。
Comments::whereIn('user_id',$users);
Usersを基本とした場合
UsersController.php
// comment_titleで検索したい
$comments = Comments::select('user_id')
->where('comment_title', $title);
// その結果を、当モデルに組み込む。
Comments::whereIn('id',$comments);
この方法がよさそう。
whereInのみの場合と比較しても大して変わらない。
ちゃんと計測はしていないけど、体感で明らかに早くなったのでよしとする。(whereHasだと1.5倍以上時間かかる)
生クエリや、left joinする方より美しく書ける。
以上。
追記
下記の方が、便利なライブラリを作成してくれています。
古のphpバージョンだと対応していない(未確認)ので、以降の記事は備忘録的な意味で残します。
https://qiita.com/mpyw/items/0761a5e44836c9bebcd5