8
11

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 5 years have passed since last update.

Laravel 6で一覧ページに検索窓とページ行数指定を付ける

Last updated at Posted at 2019-10-07

 Laravel 6でindex()コントローラとビュー(Blade)を使ってレコード一覧を作るときに、Laravel標準ページネーションを使いつつ、キーワードによる絞り込み、1ページの表示数を指定できるようにする方法を紹介します。

 指定した条件は、URLのクエリーパラメータに以下のような形で明示されるようにします。これにより、ユーザーがリンクをほかのユーザーに共有した時に、そのユーザーも同じ画面が見られます。

/customers?keyword=a&perpage=10&page=3

image.png

今回はCustomerモデルの一覧画面という設定で見ていきましょう。

コントローラ

まずはコントローラ。

CustomerController.php
    public function index(Request $request)
    {
        $query = Customer::query();

        $keyword = $request->input('keyword');
        if (!empty($keyword)) {
            $query->where('name', 'like', '%' . $keyword . '%');
        }

        $perpage = $request->input('perpage', 10);

        //paginate
        $customers = $query->paginate($perpage);
        return view('customers.index', ['customers' => $customers->appends($request->except('page')), 'request'=>$request->except('page')]);
    }

順に見ていきます。

検索キーワードと表示行数の入力をコントローラで受け取るため、Requestオブジェクトをパラメータに追加します。

public function index(Request $request)

次に検索条件を追加できるようにCustomerモデルからクエリービルダーを取得します。

        $query = Customer::query();

検索キーワードをGetパラメータから取得し、指定があればwhere句を追加します。

        $keyword = $request->input('keyword');
        if (!empty($keyword)) {
            $query->where('name', 'like', '%' . $keyword . '%');
        }

また、表示行数もGetパラメータから取得し、指定があればその数値、なければ10行とします。
Requestオブジェクトのinputメソッドに第2パラメータを指定すると、規定値として処理してくれます。

        $perpage = $request->input('perpage', 10);

指定条件で絞って、さらにページ処理(Pagination)を施した結果のCustomer一覧を取得します。

        $customers = $query->paginate($perpage);

最後にcustomers.indexというblade(ビュー)に、絞り込んだ$customersを渡します。

        return view('customers.index', ['customers' => $customers->appends($request->except('page')), 'request'=>$request->except('page')]);

このとき、customerのPaginationがpage以外のGetパラメータを適切に取り扱えるよう、以下のようにパラメータを渡しています。

'customers' => $customers->appends($request->except('page'))

さらにbladeに、手動でGetパラメータ全体(Page以外)を渡しています。

'request'=>$request->except('page')]

# ビュー

まずPaginationリンク。これは標準のまま。

index.blade.php
{{ $customers->links() }}

次に検索ボックス。

index.blade.php
<form method="get">
    @foreach ($request as $key=>$value)
        @if ($key!="keyword")
            <input type="hidden" name="{{$key}}" value="{{$value}}" />
        @endif
    @endforeach
    <input type="text" class="form-control" name="keyword" placeholder="Name" value="{{$request["keyword"] ?? ""}}">
</form>

自分のパラメータであるkeyword以外についてはhiddenで保持します。ただしpageはコントローラ側で排除したので、ここに保持されません。つまり、キーワード検索を実施すると必ず1ページ目に戻ることになります。
さらに、inputボックスの値は{{$request["keyword"] ?? ""}}とし、キーワードが既に指定されていればそれ、なければ空文字列とします。なお、??はPHP7以降で導入されたnull合体演算子という便利な三項演算子です。

同じように1ページの行数指定ドロップダウンを作ります。

index.blade.php
<form method="get">
    @foreach ($request as $key=>$value)
        @if ($key!="perpage")
            <input type="hidden" name="{{$key}}" value="{{$value}}" />
        @endif
    @endforeach
    <select class="custom-select" name="perpage" onchange="this.form.submit()">
        <option value="10" {{($request["perpage"] ?? "")==10?"selected":""}}>10</option>
        <option value="20" {{($request["perpage"] ?? "")==20?"selected":""}}>20</option>
        <option value="50" {{($request["perpage"] ?? "")==50?"selected":""}}>50</option>
        <option value="100" {{($request["perpage"] ?? "")==100?"selected":""}}>100</option>
    </select>
</form>

形は違いますがやってることは上と同じです。
本来なら行数指定がまだの場合、デフォルトの選択が何になるか明示すべきですが、デフォルトの選択肢が一番上に来ているため、初期状態の"selected"指定はなし=一番上になる、ということにして手抜きしています。

なぜcustomersに格納されているパラメータを使わないのか

 コントローラからビューに渡す$customersには、実はクエリーパラメータが格納されています。しかし、このパラメータは仕様上protectedになっていて、blade内で読むことはできません。そのため、自前で$requestをbladeに渡しているのです。

8
11
0

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
8
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?