【Laravel】ページネーション付き検索フォームを作成する方法
地味にはまったので備忘録的にコードを公開しておきます。
完成後のイメージとしてはブログのページネーション機能を意識してください。
完成予想図は以下です。
Laravelでページネーション付き検索フォームを作成するながれ
【1】投稿一覧を出力する
【2】出力したコンテンツにページネーションをつける
【3】検索フォームをつくる
【4】検索フォームをページネーションに対応させる
では、まとめていきます。
【1】投稿一覧を出力する
まずはリソースコントローラーを作成します。
$ php artisan controller:make PostController
ルーティングの設定
Route::resource('posts', 'PostController');
ポストコントローラーに以下を記述します。
public function index(){
$posts = Post::all();
return View::make('posts.index')
->with('posts', $posts);
}
ビューは以下のとおり。
<h1>投稿一覧ページ</h1>
<div>
@foreach($posts as $post)
<h2>{{ $post->title }}</h2>
<p>{{ $post->read_more }}</p>
<a href="{{ $post->id }}">続きを読む</a>
@endforeach
</div>
これで投稿一覧の表示機能が完成しました。
【2】投稿にページネーションをつける
コントローラーを以下のように変更します。
// $posts = Post::all();
$posts = Post::paginate(10);
ビューに以下を追記します。
<div class="paginate">
{{ $posts->links() }}
</div>
たったこれだけで、ページネーションが完成です。
【3】検索フォームをつくる
ビューから作っていきます。
以下の検索フォームを表示させたい場所に貼り付ければOKです。
<div class="search">
{{ Form::open(['method' => 'GET']) }}
{{ Form::input('検索する', 'q', null) }}
{{ Form::close() }}
</div>
検索フォームのメソッドを作ります。
ポストコントローラーに以下の追記します。
タイトルで検索をかけるメソッドです。
public function getSearch(){
$query = Request::get('q');
if ($query) {
$posts = Post::where('title', 'LIKE', "%$query%")->get();
}else{
$posts = Post::all();
}
return View::make('posts.index')->with('posts', $posts);
}
ルーティングの設定をします。
// 検索機能
Route::get('posts', '[email protected]');
これだけで検索フォームが完成です。
しかし、以下の状況でエラーが起きます。
1. なにかのワードで検索をかける
2. 検索結果とページネーションが表示される。
3. ページネーションをクリックする
すると、検索結果の情報が保持されなくなってしまいます。
なぜこのエラーがおきるのかを具体的に説明します。
例えば『hoge』で検索をした場合のURLは以下のようになります。
http://localhost:8000/posts?q=hoge
つぎにページネーションをクリックすると、URLは以下のようになります。
http://localhost:8000/posts?page=2
おわかりだと思いますが『?q=hoge』が消えてしまっていますね。
理想は以下のURLです。
http://localhost:8000/posts?q=hoge&page=2
では、この部分を直していきましょう。
【4】検索フォームをページネーションに対応させる
ポストコントローラーを以下のように変更します。
// $posts = Post::where('title', 'LIKE', "%$query%")->get();
$posts = Post::where('title', 'LIKE', "%$query%")->paginate(10);
// $posts = Post::all();
$posts = Post::paginate(10);
ページネーションを表示するビューを以下のように変更します。
<div class="paginate">
{{ $posts->appends(Request::only('q'))->links() }}
</div>
</code></pre>
これで完成です。Laravel便利です。
<p id="post-syokai">番外編:タイトルだけではなく、本文も検索結果に表示させる方法</p>
当記事ではタイトルを検索するフォームをつくりましたが、本文も検索でひっかかるようにしたい場合は、以下のとおりにします。
<pre><code class="language-php">
$posts = Post::where('title', 'LIKE', "%$query%")
->orWhere('content', 'LIKE', "%$query%")
->paginate(10);