PHP

【Laravel】キーワード検索機能の実装と検索文字列にマーカーを引く方法

動作環境

  • Laravel 8.40.0
  • PHP 8.0.3
  • macOS 12.0.1

今回はフォーム検索機能を実装し、複数のパラメーターやキーワードに一致したものをデータベースから取得する方法を解説したいと思います。

さらに、検索キーワードに一致した文字列は黄色のマーカーを引いて表示するようにしてみます。

コントローラーの設定

今回は、旅行サイトの口コミをデータベース化したものから、フォームに入力した内容にマッチした口コミを取得し表示するというアプリケーションを例に説明していきます。

コントローラーにsearchアクションを定義していきます。

public function search(Request $request)
    {
        $q = Kuchikomi::query();
        if(isset($request->client_id)){
            $q->where('client_id', '=',$request->client_id);
        }
        if(isset($request->OTA)){
            $q->where('OTA', '=',$request->OTA);
        }
        if(isset($request->score)){
            $q->where('score', '=',$request->score);
        }
        if(isset($request->start_date)){
            $q->where('reviewed_date', '>=',$request->start_date);
        }
        if(isset($request->end_date)){
            $q->where('reviewed_date', '>=',$request->end_date);
        }
        if(isset($request->end_date)){
            $q->where('score', '=',$request->score);
        }
        if(isset($request->keyword) && $request->keyword_type === "or"){
            $keywords = explode(",", $request->keyword);
            $q->where(function ($query) use($keywords) {
                foreach($keywords as $keyword){
                    $query->orWhere('review', 'LIKE',"%$keyword%");
                }
            });
        } elseif(isset($request->keyword)) {
            $keywords = explode(",", $request->keyword);
            foreach($keywords as $keyword){
                $q->where('review', 'LIKE',"%$keyword%");
            }
        }
        // \DB::enableQueryLog();
        $results = $q->get();
        // dd(\DB::getQueryLog());

        $results->count=count($results);

        // 文字をハイライトする
        if(isset($request->keyword)) {
            foreach($results as $result){
                $keywords = explode(",", $request->keyword);
                $result->review = $this->search_text_highlight($keywords, $result->review);
            }
        }
        // クライアントユーザー(is_admin=0)のみを抽出する
        $users=DB::table('users')->where('is_admin', 0)->get();
        return view('kuchikomis/searchResults',['results' => $results,'users'=>$users]);
    }

    /**
     * 文字列から検索したい文字を検索しヒットしたらハイライトする
     *
     * @param array $keywords 検索したいキーワード
     * @param string $target_string 検索対象の文字列
     * @return string $target_string
     */
    public function search_text_highlight($keywords, $target_string)
    {
        // 検索対象文字列が空であれば、文字列をそのまま返す
        if(empty($keywords)){
            return $target_string;
        }

        foreach($keywords as $keyword){
            // 検索文字列がヒットしたらハイライトして返す
            if( ($pos = mb_strpos($target_string, $keyword, 0, 'UTF-8')) !== false ){
                // 対象文字列から、検索文字列を取得する
                $str = mb_substr($target_string, $pos, mb_strlen($keyword, 'UTF-8'), 'UTF-8');
                // 対象文字列から検索文字列をハイライトする
                $target_string = str_replace($str, "<span style='background-color:yellow'>{$str}</span>", $target_string);
            }
        }
        return $target_string;
    }

解説

検索フォームのパラメーターによってWhere句を動的に組み立てていく

検索フォームは入力した内容によって様々な条件の組み合わせが渡ってくるので、それに対応できるように、if文でクエリを組み立てていきます。

if文をコンパクトにしたいという場合は{}を省略して下記のように1行の書き方でも可能。

if(isset($request->client_id)) $q->where('client_id', '=',$request->client_id);

実行されるSQLを確認したい場合は下記のようにクエリを囲んでみる。

クエリが複雑になってきた際に、実際どのようなSQLが実行されるか確認できるので便利です。

\DB::enableQueryLog();
$results = $q->get();
dd(\DB::getQueryLog());

検索条件にキーワード含まれている場合、マッチしたテキストに黄色マーカーを引く

検索条件にマッチしたデータを全て取得後、search_text_highlight()関数でテキストに黄色マーカーを引いていきます。

str_replaceで検索文字列を<span style='background-color:yellow'>hoge</span>に置換していくことでblade側で表示する際に黄色マーカーが引かれます。

>> 参考:【Laravel】BladeでHTMLを出力させる方法

今回はviewのフォーム部分の解説は省略いたしますが、これで検索を実行するとsearchアクションが動作し、検索結果を表示すると同時にマッチしたキーワードがあれば黄色マーカーで検索結果を表示してくれるようになります。

  • この記事を書いた人

コウダイ

文系・ノースキル・未経験・アラサー・地方住み・残業100時間超えの社畜ホテルマンから都内IT系上場企業のフルリモートWebエンジニアに転職した人。

都内IT系上場企業に勤務するWebエンジニア5年目|プログラミングスクールのテックキャンプ公式アンバサダー|新卒で手取り18万の地方ホテルマン6年→挫折→プログラミングを900時間勉強→転職活動100社以上応募→アラサー未経験から7ヶ月でフルリモートのWebエンジニアに転職し年収150万円UP|34歳2児のパパ|ブログ歴4年→月間6,000PV|エンジニア転職ノウハウ、プログラミング、Web制作、副業での稼ぎ方など、「時間や場所に縛られずに稼ぐ」方法を発信しています。

-PHP