技術

Laravel4: 1ページで複数のページネーターを使う

これ出来たとしてもデザインというかユーザビリティ的にアウトだと思うのでやらない方がいいと思うんですが、テストとかで一時的にでもやりたい事があるかもしれないのでメモ。

Laravelのバージョンは4.1.24です。

Laravel4だとrouteやcontroller等で

$users = User::paginate(15);

なんてやってから、ビューに渡して

{{ $users->links() }}

なんてやるだけで、ページ移動のためのHTMLを生成してくれてとても便利です。

これを同時に複数やるとすると以下のように書きたくなるんですが、

$users = User::paginate(15);
$blogs = Blog::paginate(15);
{{ $users->links() }}
{{ $blogs->links() }}

links()で生成されるHTMLではページ遷移の為のURLパラメーター名が”page”で固定されているため、usersの2ページ目を見ようとするとblogsも2ページ目になってしまうという風にページが同期してしまって、usersは2ページ目、blogsは3ページ目という風に別々に表示するという事が出来ません。

で、その”page”という名前は何処から来てるのかを調べると vendor/laravel/framework/src/Illuminate/Pagination/Environment.php の Environmentクラスのコンストラクタが以下のようになってました。

	/**
	 * Create a new pagination environment.
	 *
	 * @param  \Symfony\Component\HttpFoundation\Request  $request
	 * @param  \Illuminate\View\Environment  $view
	 * @param  \Symfony\Component\Translation\TranslatorInterface  $trans
	 * @param  string  $pageName
	 * @return void
	 */
	public function __construct(Request $request, ViewEnvironment $view, TranslatorInterface $trans, $pageName = 'page')
	{
		$this->view = $view;
		$this->trans = $trans;
		$this->request = $request;
		$this->pageName = $pageName;
		$this->setupPaginationEnvironment();
	}

$pageName引数には外部から値が指定される事もないみたいみたい(独自にそういうコードを書いてたら別ですが)なので、ここが”page”の出所となります。

この’page’をpaginate()を呼ぶ度に変更出来れば目的は達成できそうです。
それをやる方法は色々と考えられるのですが、なるべくライブラリ側に手を加えず、なおかつ簡単に書ける方法を考えたところ、以下のようにするのが一番問題が少ないのではないかと思いました。

$users = User::paginate(15);

$paginatorEnv = App::getFacadeApplication()['paginator'];
$paginatorEnv->setPageName('blogpage');
$blogs = Blog::paginate(15);
{{ $users->links() }}
{{ $blogs->links() }}

2つ目のpaginate()を呼ぶ直前にIlluminate\Pagination\Environmentのインスタンスを得てpageNameメンバの値を変える(ただしpageNameはprotectedなのでメンバ関数経由で変更する)だけですね。
これでusersの分は”page”というパラメーター名に、blogsの分は”blogpage”というパラメーター名になります。

コメントを残す

メールアドレスが公開されることはありません。



※画像をクリックして別の画像を表示

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください