6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravel のwhereHasをwhereInに置き換える

Last updated at Posted at 2020-12-27

難しいクエリを作りたくない

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

6
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?