24
16

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 1 year has passed since last update.

【Laravel】EloquentでOR検索する方法

Last updated at Posted at 2022-02-21

環境

Laravel: 8.82.0
PHP: 8.1.2

OR検索

文字列で検索ができるようにOR検索を導入しようとしたときでした。
とりあえず少し調べて、以下のコードで実行しました。

失敗パターン
$keyword = $request->keyword;

$user = Auth::user();
$items = $user->items()->where("name", "like", "%".$keyword."%")
            ->orWhere("text", "like", "%".$keyword."%")->get();

これで OR 検索をしようとすると、
->where("name", $keyword)は、ログインしている User の結果だけを返すのですが、
->orWhere("text", $keyword)は、全ての Userの結果を返すのです。

なんでやねん!

とツッコミを入れながらも、改善案を探すことにしました。

ダメな理由

ダメな理由は条件の書き方にありました。

$useritemに対してnameまたはtextがキーワードを含んでいたら、というつもりで書いていました。
つまり、itemに対しての条件で考えていたのです。

しかし、先程の記述では
$useritemに対してnameがキーワードを含む
または、$userに対してtextがキーワードを含んでいたらになっていたのです。

その際に、$usertextというカラムが存在しないため、
全件一致という扱いを受けて、実質$user->all()全ての User)と同義になってしまったという訳です。

これでは想定している動作とは異なるので、
条件の書き方を修正する必要があります。

whereでまとめる

検索してみると、whereをまとめることができるようです!
早速まとめてみます!

失敗パターン
$keyword = $request->keyword;

$user = Auth::user();
$items = $user->items()->where(function ($query) {
            $query->where("name", "like", "%".$keyword."%")
                ->orWhere("text", "like", "%".$keyword."%");
            })->get();

これで大丈夫と思ったのですが、エラーが出ます。
スコープの問題で、「$keywordなんて知らない」といわれます。

これでも悩みました。。。

useで変数を渡す

そうしていると、先輩が解決方法を教えてくださり、

成功パターン
$keyword = $request->keyword;

$user = Auth::user();
$items = $user->items()->where(function ($query) use ($keyword) {
            $query->where("name", "like", "%".$keyword."%")
                ->orWhere("text", "like", "%".$keyword."%");
            })->get();

useを使って解決できたのでした。

24
16
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
24
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?