質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

解決済

2回答

418閲覧

Laravel5.4のクエリビルダーでwhereやorWhereなどを使っての条件抽出について

do_slice

総合スコア26

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

0グッド

0クリップ

投稿2017/12/14 14:37

Laravelのクエリビルダーについて質問させてください。

Laravel5.4のクエリビルダーでwhereやorWhereなどを使っての条件抽出について
うまくいかずに困っています。

記事を表示するサイトに検索の機能を作ろうと思い、
viewの検索窓から$keywordをコントローラーに送り
コントローラーで下記のような形でwhereやorWhereなどを使ってデータの抽出処理をしています。

PHP

1 public function topSearch(Request $request){ 2 3 $keywords = $request->input('keywords'); 4 //省略 5 6//検索の前にドラフトと掲載前の記事を除外する 7 $query = Board::query(); 8 $query->where(function($query) use($now){ 9 $query->where('status', '!=', 'draft') 10 ->where('published_at','<=', $now) 11 }); 12 13 14//検索条件で抽出 15 $query->where('title','like','%'.$keywords.'%')->orWhere('description','like','%'.$keywords.'%'); 16 $query->orWhere('title','like','%'.$keywords.'%')->orWhere('description','like','%'.$keywords.'%'); 17 18 19 $query->orderBy('created_at', 'desc'); 20 $boards = $query->paginate(20); 21 22//省略

この際に前段の

PHP

1 $query->where('status', '!=', 'draft') 2 ->where('published_at','<=', $now)

が効いておらず、$boardsの中にドラフトと掲載前の記事も含まれてしまします。
キーワードでの検索の処理の条件の方は効いており抽出されています。

下記のような記述でも結果は同じでした。

PHP

1$query = Board::query(); 2$query->where('status', '!==', 'draft'); 3$query->where('published_at','<=', $now);

暫定処理で表示したくないコンテンツはviewのbladeの方で

PHP

1@forelse($post_boards as $post_board) 2@if($post_board->status != 'draft') 3@if($post_board->published_at <= $now) 4//省略 5<li> 6 {!! mb_strimwidth( strip_tags( $board->description ), 0, 155, '...', 'UTF-8') !!} 7 <a href="{{ route('boards.show', ['id' => $board->id]) }}">[ReadMore]</a> 8</li> 9//省略 10@endif 11@endif 12@endforelse

というような処理で非表示にしているのですが、
$boardsの抽出のところでできれば制御したいと思っています。

whereやorWhereの使い方の基本的なところが理解できていないのかもしれませんが、
ヒントをいただければ幸いです。

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

https://laravel.com/docs/5.5/queries
Parameter Groupingのところで書いているとおり、whereに関数を渡したらその内部をカッコで囲むっていう感じになるので、

php

1$query = Board::query(); 2 $query->where(function($query) use($now){ 3 $query->where('status', '!=', 'draft') 4 ->where('published_at','<=', $now) 5 }); 6 7 8//検索条件で抽出 9 $query->where('title','like','%'.$keywords.'%')->orWhere('description','like','%'.$keywords.'%'); 10 $query->orWhere('title','like','%'.$keywords.'%')->orWhere('description','like','%'.$keywords.'%');

だと
where (status != 'draft' and published_at <= '$nowの値')
and title like %{$keywords}%
or description like %{$keywords}%
or titlelike %{$keywords}%
or description like %{$keywords}%

となってしまうのではないでしょうか

php

1$query = Board::query(); 2 $query->where(function($query) use($now){ 3 $query->where('status', '!=', 'draft') 4 ->where('published_at','<=', $now) 5 }); 6 7 8//検索条件で抽出 9$query->where(function($query) use($keywords){ 10 $query->where('title','like','%'.$keywords.'%')->orWhere('description','like','%'.$keywords.'%'); 11 $query->orWhere('title','like','%'.$keywords.'%')->orWhere('description','like','%'.$keywords.'%'); 12});

こうかなっていう感じがしますね。

※QueryBuilderには

php

1$query->toSql(); 2$query->getBindings();

っていう関数があるのでどういうSQL文になってるか出力してみるといいかもしれません。

投稿2017/12/14 15:47

rururu3

総合スコア5545

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

do_slice

2017/12/15 07:36

rururu3様 ありがとうございます! 教えていただいた通りで想定通りの動きをしました。 勉強になりました。ベストアンサーとさせていただきました。
guest

0

おそらくこのあたりが原因では?

PHP

1 $query->where('title','like','%'.$keywords.'%')->orWhere('description','like','%'.$keywords.'%'); 2 $query->orWhere('title','like','%'.$keywords.'%')->orWhere('description','like','%'.$keywords.'%');

ここがやりたいことは「タイトルにキーワードを含む、または説明文にキーワードを含む」だと思うのですが、まず2回もtitleとdescriptionのorWhereが書いてあるのが多分無駄ですし、このorWhereがこの位置だとこれまでのwhereまたはこのorWhereになってしまいます。多分出来上がっているクエリはこんな感じです。

(ドラフトじゃない AND 公開日以降) AND タイトルにキーワードを含む OR 説明文にキーワードを含む OR タイトルにキーワードを含む OR 説明文にキーワードを含む

おそらくやりたいことはこうですよね?

(ドラフトじゃない AND 公開日以降) AND (タイトルにキーワードを含む OR 説明文にキーワードを含む)

だとしたらクエリの書き方はこうなると思います。

PHP

1$query = Board::query(); 2$query->where(function($query) use($now){ 3 $query->where('status', '!=', 'draft') 4 ->where('published_at','<=', $now); 5}); 6 7 8//検索条件で抽出 9$query->where(function($query) { 10 $query->where('title','like','%'.$keywords.'%') 11 ->orWhere('description','like','%'.$keywords.'%'); 12});

最終的に出来上がったクエリの形を確認するにはDB::getQueryLogを使います。
https://qiita.com/keita-nishimoto/items/0734d8f615b7b0146cb8

投稿2017/12/15 00:58

masaya_ohashi

総合スコア9206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

masaya_ohashi

2017/12/15 00:59

ってまったく同じこと言ってるだけやないかーい!私の回答は無視してください…
do_slice

2017/12/15 07:39

masaya_ohashi様 レスありがとうございましたmm
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問