Laravel 6でindex()コントローラとビュー(Blade)を使ってレコード一覧を作るときに、Laravel標準ページネーションを使いつつ、キーワードによる絞り込み、1ページの表示数を指定できるようにする方法を紹介します。
指定した条件は、URLのクエリーパラメータに以下のような形で明示されるようにします。これにより、ユーザーがリンクをほかのユーザーに共有した時に、そのユーザーも同じ画面が見られます。
/customers?keyword=a&perpage=10&page=3
今回はCustomerモデルの一覧画面という設定で見ていきましょう。
コントローラ
まずはコントローラ。
    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リンク。これは標準のまま。
{{ $customers->links() }}
次に検索ボックス。
<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ページの行数指定ドロップダウンを作ります。
<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に渡しているのです。
