Written by Manabu Bannai

【Laravel】ページネーション付き検索フォームを作成する方法

Laravel PROGRAMMING

地味にはまったので備忘録的にコードを公開しておきます。
完成後のイメージとしてはブログのページネーション機能を意識してください。
完成予想図は以下です。

ページネーション

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);