Laravelのデフォルトのペジネーションが長さの調整はしにくいわ、treee dotsは邪魔だわ、デザインの変更はしづらいわで絶妙に使いづらかったので自作しました。
完成系
環境
- PHP 7.3
- Laravel 5.8
ペジネーションビューの作成
まずlaravelで以下のコマンドを叩くと自動でresources/views/vendor/pagination
ディレクトリを作成して、さらにいくつかのデフォルトなどで使用されるペジネーションビューを設置してくれます。
php artisan vendor:publish --tag=laravel-pagination
ペジネータインスタンスのlinks()
メソッドでは、先ほど作成されたディレクトリ下にあるbootstrap-4.blade.php
がデフォルトのペジネーションビューに設定されています。
ちょっとだけペジネーションのHTMLをいじりたいならこれを直接編集してもいいですが、今回は一から作り直したいのでpagination
ディレクトリ下に新しくペジネーションビューを作成します。
resources
├ ~
└ views
└ vendor
└pagination
├bootstrap-4.blade.php
├ ~
└ original_pagination_view.blade.php <-新しくファイルを作成
ペジネーションビューの雛形
まずはペジネーションビューの雛形を作成します。
@if ($paginator->hasPages())
<ul class="pagination" role="navigation">
{{-- First Page Link --}}
<!-- 最初のページへのリンク -->
{{-- Previous Page Link --}}
<!-- 前のページへのリンク -->
{{-- Pagination Elemnts --}}
{{-- Array Of Links --}}
<!-- それぞれのページへのリンク -->
{{-- Next Page Link --}}
<!-- 次のページへのリンク -->
{{-- Last Page Link --}}
<!-- 最後のページへのリンク -->
</ul>
@endif
基本的にペジネーションビューは$paginator->xxx()
といった形のペジネータインスタンスメソッドを使用して作成していきます。
hasPages()
はクエリビルダやEloquent queryでpaginate()
メソッドなどが使用された時に与えられたアイテムの数と引数を比較して引数よりも多かった場合Trueを返します。たぶん。
あとは好みで<nav>
などをつけたりclass
を書き加えたりしましょう。
今後はこの雛形に沿って各機能を実装していきます。
First Page Linkの作成
{{-- First Page View --}}
<li class="page-item {{ $paginator->onFirstPage() ? ' disabled' : '' }}">
<a class="page-link" href="{{ $paginator->url(1) }}">«</a>
</li>
onFirstPage()
はペジネータが最初のページを扱っていればTrueを返し、そうでないならFalseを返します。
url()
は()内で指定したページのURLを取得します。
現在のページが最初のページの時にはclass
にdisabled
を追加することでリンクを無効化しています。
Previous Page Linkの作成
{{-- Previous Page Link --}}
<li class="page-item {{ $paginator->onFirstPage() ? ' disabled' : '' }}">
<a class="page-link" href="{{ $paginator->previousPageUrl() }}">‹</a>
</li>
First Page Linkとほとんど一緒ですね。
previousPageUrl()
は現在のページから一つ前のページのURLを取得しています。
Array Of Linksの作成
リンク数の管理を行う際、直接ペジネーションビュー内に変数を作成してもいいのですが、いちいち変更するのが面倒なので定数を作成しましょう。
config
ディレクトリ下にconst.php
を作成して次のように記述しましょう。
<?php
//paginate
'PAGINATE' => [
'LINK_NUM' => '5', //paginationの一度に表示するリンクの数
],
これで簡単にページのリンクを表示する数を管理・変更できるようになりました。
次はこれを使って各ページへのリンクを表示するコードを書いていきます。
{{-- Pagination Elemnts --}}
{{-- Array Of Links --}}
{{-- 定数よりもページ数が多い時 --}}
@if ($paginator->lastPage() > config('const.PAGINATE.LINK_NUM'))
{{-- 現在ページが表示するリンクの中心位置よりも左の時 --}}
@if ($paginator->currentPage() <= floor(config('const.PAGINATE.LINK_NUM') / 2))
<?php $start_page = 1; //最初のページ ?>
<?php $end_page = config('const.PAGINATE.LINK_NUM'); ?>
{{-- 現在ページが表示するリンクの中心位置よりも右の時 --}}
@elseif ($paginator->currentPage() > $paginator->lastPage() - floor(config('const.PAGINATE.LINK_NUM') / 2))
<?php $start_page = $paginator->lastPage() - (config('const.PAGINATE.LINK_NUM') - 1); ?>
<?php $end_page = $paginator->lastPage(); ?>
{{-- 現在ページが表示するリンクの中心位置の時 --}}
@else
<?php $start_page = $paginator->currentPage() - (floor((config('const.PAGINATE.LINK_NUM') % 2 == 0 ? config('const.PAGINATE.LINK_NUM') - 1 : config('const.PAGINATE.LINK_NUM')) / 2)); ?>
<?php $end_page = $paginator->currentPage() + floor(config('const.PAGINATE.LINK_NUM') / 2); ?>
@endif
{{-- 定数よりもページ数が少ない時 --}}
@else
<?php $start_page = 1; ?>
<?php $end_page = $paginator->lastPage(); ?>
@endif
{{-- 処理部分 --}}
@for ($i = $start_page; $i <= $end_page; $i++)
@if ($i == $paginator->currentPage())
<li class="page-item active"><span class="page-link">{{ $i }}</span></li>
@else
<li class="page-item"><a class="page-link" href="{{ $paginator->url($i) }}">{{ $i }}</a></li>
@endif
@endfor
config('const.PAGINATE.LINK_NUM')
でconst.php
に書いたLINK_NUM
を呼び出しています。
またlastPage()
は最後のページ数を、currentPage()
は現在のページ数を、url($page)
は入力されたページ数のURLをそれぞれ返します。
だいぶ長くなってしまいましたが、難しいことは書いてないので何をやっているかは理解できるかと思います。
強いて言えば定数を$link_num
などの変数に入れて使用したり、$elements
などを用いて書き換えるとコードがより読みやすくなるかもしれません。
Next Page LinkとLast Page Link
FirstやPreviousとほぼ一緒なのでさらっと書いていきましょう。
{{-- Next Page Link --}}
<li class="page-item {{ $paginator->currentPage() == $paginator->lastPage() ? ' disabled' : '' }}">
<a class="page-link" href="{{ $paginator->nextPageUrl() }}">›</a>
</li>
{{-- Last Page Link --}}
<li class="page-item {{ $paginator->currentPage() == $paginator->lastPage() ? ' disabled' : '' }}">
<a class="page-link" href="{{ $paginator->url($paginator->lastPage()) }}">»</a>
</li>
nextPageUrl()
は次のページのURLを出力します。
これでオリジナルのペジネーションビューが完成しました!
オリジナルのペジネーションビューを反映させる
ペジネーションビューが完成しましたが、デフォルトのペジネーションビューにはbootstrap-4.blade.php
が指定してあります。
なのでoriginal_pagination_view.blade.php
が使用されるように変更しましょう。
デフォルト以外のペジネーションビューを使用する場合は、links()
メソッドをしようする際に第一引数にビュー名を指定するか、AppServiceProvider
でデフォルトとして設定します。
links()で引数に指定する方法
こちらの方法ではいつも使っているlinks()
メソッドで引数に使いたいペジネーションビューを指定するだけで使用することができます。
{{ $items->links('original_pagination_view.blade.php') }}
AppServiceProviderで設定する方法
オリジナルのペジネーションビューを全てのページのデフォルトとして使用したい場合、app/Providers
にあるAppServiceProvider
を編集します。
use Illuminate\Pagination\Paginator; //<-追加する
-------------------------
public function boot()
{
Paginator::defaultView('original_pagination_view.blade.php');
}
これでオリジナルのペジネーションビューがデフォルトとして使用されるようになりました。
もしシンプルペジネーションのビューを適用したい場合はdefaultSimpleView()
を使用してください。
最後に
Array Of Linksがもうちょっとスマートに書ける…かもしれないけど、いい方法が思いつかなかったので未来の自分に丸投げします。
あとは$elements
についてあまり理解できてないので、機会があればそれを利用したペジネーションビューを作ってみたいと思います。