41
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Laravelでリンク数を可変で決められるペジネーションの自作方法

Posted at

Laravelのデフォルトのペジネーションが長さの調整はしにくいわ、treee dotsは邪魔だわ、デザインの変更はしづらいわで絶妙に使いづらかったので自作しました。

完成系

こんな感じ
スクリーンショット 2019-05-11 18.40.33.png

環境

  • PHP 7.3
  • Laravel 5.8

ペジネーションビューの作成

まずlaravelで以下のコマンドを叩くと自動でresources/views/vendor/paginationディレクトリを作成して、さらにいくつかのデフォルトなどで使用されるペジネーションビューを設置してくれます。

vendor:publishコマンド
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 <-新しくファイルを作成

ペジネーションビューの雛形

まずはペジネーションビューの雛形を作成します。

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の作成

original_pagination_view.blade.php
{{-- First Page View --}}
    <li class="page-item {{ $paginator->onFirstPage() ? ' disabled' : '' }}">
        <a class="page-link" href="{{ $paginator->url(1) }}">&laquo;</a>
    </li>

onFirstPage()はペジネータが最初のページを扱っていればTrueを返し、そうでないならFalseを返します。
url()は()内で指定したページのURLを取得します。

現在のページが最初のページの時にはclassdisabledを追加することでリンクを無効化しています。

Previous Page Linkの作成

original_pagination_view.blade.php
{{-- Previous Page Link --}}
    <li class="page-item {{ $paginator->onFirstPage() ? ' disabled' : '' }}">
        <a class="page-link" href="{{ $paginator->previousPageUrl() }}">&lsaquo;</a>
    </li>

First Page Linkとほとんど一緒ですね。
previousPageUrl()は現在のページから一つ前のページのURLを取得しています。

Array Of Linksの作成

リンク数の管理を行う際、直接ペジネーションビュー内に変数を作成してもいいのですが、いちいち変更するのが面倒なので定数を作成しましょう。
configディレクトリ下にconst.phpを作成して次のように記述しましょう。

const.php
<?php    
    //paginate
    'PAGINATE' => [
        'LINK_NUM' => '5', //paginationの一度に表示するリンクの数
    ],

これで簡単にページのリンクを表示する数を管理・変更できるようになりました。

次はこれを使って各ページへのリンクを表示するコードを書いていきます。

original_pagination_view.blade.php
{{-- 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とほぼ一緒なのでさらっと書いていきましょう。

original_pagination_view.blade.php
{{-- Next Page Link --}}
    <li class="page-item {{ $paginator->currentPage() == $paginator->lastPage() ? ' disabled' : '' }}">
        <a class="page-link" href="{{ $paginator->nextPageUrl() }}">&rsaquo;</a>
    </li>

{{-- Last Page Link --}}
    <li class="page-item {{ $paginator->currentPage() == $paginator->lastPage() ? ' disabled' : '' }}">
        <a class="page-link" href="{{ $paginator->url($paginator->lastPage()) }}">&raquo;</a>
    </li>

nextPageUrl()は次のページのURLを出力します。

これでオリジナルのペジネーションビューが完成しました!

オリジナルのペジネーションビューを反映させる

ペジネーションビューが完成しましたが、デフォルトのペジネーションビューにはbootstrap-4.blade.phpが指定してあります。
なのでoriginal_pagination_view.blade.phpが使用されるように変更しましょう。

デフォルト以外のペジネーションビューを使用する場合は、links()メソッドをしようする際に第一引数にビュー名を指定するか、AppServiceProviderでデフォルトとして設定します。

links()で引数に指定する方法

こちらの方法ではいつも使っているlinks()メソッドで引数に使いたいペジネーションビューを指定するだけで使用することができます。

index.blade.php
{{ $items->links('original_pagination_view.blade.php') }}

AppServiceProviderで設定する方法

オリジナルのペジネーションビューを全てのページのデフォルトとして使用したい場合、app/ProvidersにあるAppServiceProviderを編集します。

AppServiceProvider.php
use Illuminate\Pagination\Paginator; //<-追加する

-------------------------

public function boot()
{
    Paginator::defaultView('original_pagination_view.blade.php');
}

これでオリジナルのペジネーションビューがデフォルトとして使用されるようになりました。

もしシンプルペジネーションのビューを適用したい場合はdefaultSimpleView()を使用してください。

最後に

Array Of Linksがもうちょっとスマートに書ける…かもしれないけど、いい方法が思いつかなかったので未来の自分に丸投げします。
あとは$elementsについてあまり理解できてないので、機会があればそれを利用したペジネーションビューを作ってみたいと思います。

参考文献

41
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?