Laravel

【Laravel】キーワード検索機能の実装方法(複数キーワード、部分一致)

タクマ

こんにちは!タクマです。

31歳未経験からエンジニア転職に成功し、

2021年3月より都内の受託開発企業にてWebエンジニアとして働いています。

今回はLaravelのキーワード検索機能の実装方法を解説します。

「ポートフォリオにキーワード検索機能を導入したい」

「キーワード検索機能の実装方法がわからない」

という方はこの記事を読めば、キーワード検索機能が実装できるようになりますので、ぜひ最後まで読んでください。

前提条件

  • usersテーブルにnameカラムがあるものとする。
  • ユーザー一覧ページに検索フォームがあり、そこでユーザー名検索ができるものとする。
  • ユーザー一覧ページはルーティング、モデル、ビュー、コントローラの実装が完了しており、ユーザーの一覧が表示されているものとする。($usersという変数をforeachで回して各ユーザーの名前が一覧で出ている状態)
  • これから出てくるコードのタグの中のBootstrapのクラスについての詳しい解説はしないものとする。

Viewに検索フォームを追加

<form class="mb-2 mt-4 text-center" method="GET" action="{{ route('users.index') }}">
    <input class="form-control my-2 mr-5" type="search" placeholder="ユーザー名を入力" name="search" value="@if (isset($search)) {{ $search }} @endif">
    <div class="d-flex justify-content-center">
        <button class="btn btn-info my-2" type="submit">検索</button>
        <button class="btn btn-secondary my-2 ml-5">
            <a href="{{ route('users.index') }}" class="text-white">
                クリア
            </a>
        </button>
    </div>
</form>

@foreach($users as $user)
    <a href="{{ route('users.show', ['user' => $user]) }}">
        {{ $user->name }}
    </a>
@endforeach


<div>
 // 下記のようにページネーターを記述するとページネートで次ページに遷移しても、検索結果を保持する
    {{ $institutions->appends(request()->input())->links() }}
</div>

上記コードについて解説します。

まずフォームの送信先はユーザー一覧ページとします。

formタグのvalue="@if (isset($search)) {{ $search }} @endif"で検索した後に、検索した値をフォーム内に保持することができます。

$searchは後ほどコントローラーから渡される変数です)

クリアボタンは検索した値をクリアするボタンです。

コントローラーに検索機能に関するコードを追加

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;

class UserController extends Controller
{

    /**
     * ユーザー一覧
     * @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
     */
    public function index(Request $request)
    {
        // ユーザー一覧をページネートで取得
        $users = User::paginate(20);

       // 検索フォームで入力された値を取得する
        $search = $request->input('search');

        // クエリビルダ
        $query = User::query();

       // もし検索フォームにキーワードが入力されたら
        if ($search !== null) {

            // 全角スペースを半角に変換
            $spaceConversion = mb_convert_kana($search, 's');

            // 単語を半角スペースで区切り、配列にする(例:"山田 翔" → ["山田", "翔"])
            $wordArraySearched = preg_split('/[\s,]+/', $spaceConversion, -1, PREG_SPLIT_NO_EMPTY);


            // 単語をループで回し、ユーザーネームと部分一致するものがあれば、$queryとして保持される
            foreach($wordArraySearched as $value) {
                $query->where('name', 'like', '%'.$value.'%');
            }

    // 上記で取得した$queryをページネートにし、変数$usersに代入
            $users = $query->paginate(20);

        }

        // ビューにusersとsearchを変数として渡す
        return view('users.index')
            ->with([
                'users' => $users,
                'search' => $search,
            ]);
    }
}

今回のキーワード検索は、複数ワードの部分一致に対応しています。

たとえば、下記のようなusersテーブルがあったとします。

idname
1高橋健太
2山田翔太
3佐藤信一
4江藤裕太
5山田浩二

「山田」と検索するとid2とid5が検索結果として返ってきますが、上記コードのように「山田 翔」と検索するとid2のみが結果として返ってくる、複数ワードの部分一致に対応した検索機能となっております。

その他コントローラの説明はコードの上のコメントを読んでください。

以上で検索機能の実装が完了です!

さいごに

いかがでしたでしょう?

キーワード検索機能が実装できましたでしょうか?

ご質問やご指摘等ある方はコメントしていただければ返信させていただきます。

これからもエンジニアの方、プログラミング初学者の方に役に立つ記事を更新していきますのでよろしくお願いします!

Twitterでも情報発信をしていますので、よかったらフォローをお願いします(^^)

Webエンジニア
タクマ
埼玉県出身の31歳

30歳からプログラミングを始め31歳でWebエンジニアに転職成功。

現在は都内の受託開発企業にてサーバーサイドエンジニアをしています。

\ Follow me /

COMMENT

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA