OctoberCMSのrainlab/blogにてページャー(pagination)をスマートに実装する方法

OctoberCMS日本代表(自称)の巨匠です。
今回は、OctoberCMSの便利なプラグイン「rainlab/blog」のページャー(pagination)について、
デフォルトのやり方だと記事が多くなると大量のボタン(1.2.3.4.5….)が表示されてしまう問題を解決しました。

まずはこちらをご覧ください。

溢れんばかりのページャーボタン。
こちらを、現在の記事から5件先のボタンまでを表示させていきたいと思います。

修正するファイルは一つでOKです。
デフォルトのテーマを使っている場合は、

/plugins/rainlab/blog/components/posts/default.htm

が対象ファイルになりますが、私の場合は自分でテンプレートを作って実装したので。

/themes/themename/partials/newslist/default.htm

になります。

デフォルトのソースコード

<div class="pagenation-box">
{% if posts.lastPage > 1 %}
    <ul class="pagination">
        {% if posts.currentPage > 1 %}
           <li><a href="{{ this.page.baseFileName|page({ (pageParam): (posts.currentPage-1) }) }}">&larr; Prev</a></li>
        {% endif %}

        {% for page in 1..posts.lastPage %}
           <li class="{{ posts.currentPage == page ? 'active' : null }}">
              <a href="{{ this.page.baseFileName|page({ (pageParam): page }) }}">{{ page }}</a>
           </li>
        {% endfor %}
                    
        {% if posts.lastPage > posts.currentPage %}
            <li><a href="{{ this.page.baseFileName|page({ (pageParam): (posts.currentPage+1) }) }}">Next &rarr;</a></li>
        {% endif %}
     </ul>
{% endif %}
</div>

問題なのはfor文の条件のところなのですが…。

{% for page in 1..posts.lastPage %}

このままだと1ページ目から最後までをループさせているので、記事が増えればその分ボタンも増えるロジックです。
今回は現在より5ページ先のボタンまで表示させたいので、if文を使って変数を作りました。

編集後のソースコード

<div class="pagenation-box">
{% if posts.lastPage > 1 %}
    <ul class="pagination">
        {% if posts.currentPage > 1 %}
           <li><a href="{{ this.page.baseFileName|page({ (pageParam): (posts.currentPage-1) }) }}">&larr; Prev</a></li>
        {% endif %}

        {% if posts.currentPage < posts.lastPage-4 %}
           {% set pagecount = posts.currentPage+4 %}
        {% else %}
           {% set pagecount = posts.lastPage - posts.currentPage + posts.currentPage %}
        {% endif %}
        {% for page in posts.currentPage..pagecount %}
           <li class="{{ posts.currentPage == page ? 'active' : null }}">
              <a href="{{ this.page.baseFileName|page({ (pageParam): page }) }}">{{ page }}</a>
           </li>
        {% endfor %}
                    
        {% if posts.lastPage > posts.currentPage %}
            <li><a href="{{ this.page.baseFileName|page({ (pageParam): (posts.currentPage+1) }) }}">Next &rarr;</a></li>
        {% endif %}
     </ul>
{% endif %}
</div>

posts.currentPageは現在見ているページで、posts.lastPageは最後のページの値が既に格納されています。

{% if posts.currentPage < posts.lastPage-4 %}

この処理がなぜ必要かというと、例えば最後のページから一つ前のページを見ていても、5つのボタンが表示されリンク先の存在しないボタンが作られてしまいます。
それを回避するために、現在見ているページが最後より4ページ未満だったら、繰り返しする数も減らす必要があるためです。
条件がtrueだった場合は普通に4回繰り返し(結果5つのボタンが表示される)

{% set pagecount = posts.currentPage+4 %}

falseだった場合は最後のページ数から現在のページ数を引いて、最後に現在のページを足すことで最後の方でも正常に動作してくれます。

{% set pagecount = posts.lastPage - posts.currentPage + posts.currentPage %}

pagecountという変数に値が格納されていますので、for文で

{% for page in posts.currentPage..pagecount %}

としてあげることで、意図する動きになりました。

正直、タイトルにある「スマートに実装」という意味では、もっとキレイにできそうな気もしますが…。
あとは現在見ているページからスタートするのではなくて現在見ているページから3ページは前後できるようにしたいですね。
まぁ、このソースコードが理解出来れば、大したことないロジックにはなると思います。

参考まで。

Leave a Reply

Your email address will not be published. Required fields are marked *

sixteen − one =