「ページネーションのデータを変える」の続きです。検索画面を用意して検索結果をページネーションします。
検索画面のページネーション
まず、こんな検索画面を作りたいです。
検索項目に値を入れると、値により絞り込まれた検索結果が表示されます。ごく普通の検索画面です。画面の右下にはページネーションも表示されます。ここでは1画面に2レコードだけ表示です。
routeの定義は、GETだけで十分です。そう、検索条件はすべてURLに入れます。
... Route::get('/search', [SearchController::class, 'index'])->name('search'); ..
コントローラの作成も簡単です。あまりにも短いのでカットせずにすべて見せてしまいます。
namespace App\Http\Controllers; use App\Models\User; use Illuminate\Http\Request; class SearchController extends Controller { public function index(Request $request) { $query = User::query(); if ($value = $request->name) { $query->where('name', 'like', "%{$value}%"); } if ($value = $request->email) { $query->where('email', 'like', "%{$value}%"); } $users = $query->paginate(2); return view('user.search', compact('users')); } }
しかし、このコード大いに問題ありです。先の画面でページネーションの2ページをクリックすると、
検索結果3件だったのに10件になっているし、ページネーションも2ページから5ページに。2ページ目なら表示するのは1件のみでは。
おかしいところだらけです。一番の問題はGETだから、ブラウザのURLには入力した値が追加されるのに、?page=2だけです。
この問題の解決はとても簡単です。
上のコントローラのコードで、withQueryString()
を以下のように追加するだけなのです。
... public function index(Request $request) { $query = User::query(); if ($value = $request->name) { $query->where('name', 'like', "%{$value}%"); } if ($value = $request->email) { $query->where('email', 'like', "%{$value}%"); } $users = $query->paginate(2)->withQueryString(); //ここに追加 return view('user.search', compact('users')); } ...
修正した2ページ目の画面です。
URLに?email=example.com&page=2
とクエリーの文字列が入っていますね。
クエリーをリファクター
上のコントローラのコードでは条件文のif
を使い検索のクエリーを作成しています。
それ自体は問題は何もありません。すでに十分わかりやすいです。
しかし、Laravel風にすると以下のようにも書くことができます。
... class SearchController extends Controller { public function index(Request $request) { $query = User::query() ->when($request->name, function($query, $value) { return $query->where('name', 'like', "%{$value}%"); }) ->when($request->email, function($query, $value) { return $query->where('email', 'like', "%{$value}%"); }); $users = $query->paginate(2)->withQueryString(); return view('user.search', compact('users', 'request')); } } ...
whereでなくwhenの関数となっているところに注意してください。最初の引数の値が存在するなら次で定義する匿名関数を実行です。
メルマガ購読の申し込みはこちらから。