Laravel4、ペギネーションリンクを取り替える

タグ: Laravel4  

これは、Laravel Advent Calendar 2013 の6日目の記事です。

前日に引き続き、Laravelに巣食う悪の権化、悪魔博士改め、川瀬が担当します。

ペギネーションの表示形式は、手を加えなくても切り替えられます。Laravelが用意している3種類は、app/coinfig/view.phpの中の設定を変更し、切り替えます。

しかし、これらはCSSフレームワークのTwitter Bootstrapを利用しています。じゃあ、Bootstrap以外に切り替えられるのかと言えば、そのままでは無理で、多少工夫をしなくてはなりません。

今回、Foundationが新しいバージョンをリリースしたので、Foundation5に対応する実例をご覧ください。

ビューファイルの切り替え

Laravel4が用意しているビューファイルは、vendor/laravel/framework/src/Illuminate/Pagination/views/に存在しています。

もちろん、これらはFoundation5に対応していませんので、そのまま使えません。

通常のビューのように、app/viewsフォルダー下にビューを作成します。今回はapp/views/pagination/foundation5.phpファイルを作成します。

<?php $presenter = new Foundation5Presenter( $paginator ); ?>

<?php if( $paginator->getLastPage() > 1 ): ?>
    <ul class="pagination">
        <?php echo $presenter->render(); ?>
    </ul>
<?php endif; ?>

ペギネーションのビューファイルは、似たような構成になります。最初にプレゼンタークラスのインスタンスを取得し、そのrenderメソッドを呼び出しています。

今回作成したのは、Foundation5Presenterクラスです。このクラスは本来PSR-0に基づきローディングさせたほうが良いと思いますが、指定の手間を省くため、modelsディレクトリー下に作成しましょう。app/models/Foundation5Presenter.phpです。

<?php

use Illuminate\Pagination\BootstrapPresenter;

/**
 * Foundation 5 presenter
 *
 * Override methods include hard coded html tags.
 */
class Foundation5Presenter extends BootstrapPresenter{

    /**
     * Create a range of pagination links.
     *
     * @param  int  $start
     * @param  int  $end
     * @return string
     */
    public function getPageRange($start, $end)
    {
        $pages = array();

        for ($page = $start; $page <= $end; $page++)
        {
            // If the current page is equal to the page we're iterating on, we will create a
            // disabled link for that page. Otherwise, we can create a typical active one
            // for the link. These views use the "Twitter Bootstrap" styles by default.
            if ($this->currentPage == $page)
            {
                $pages[] = '<li class="current"><span>'.$page.'</span></li>';
            }
            else
            {
                $pages[] = $this->getLink($page);
            }
        }

        return implode('', $pages);
    }

    /**
     * Get the previous page pagination element.
     *
     * @param  string  $text
     * @return string
     */
    public function getPrevious($text = '&laquo;')
    {
        // If the current page is less than or equal to one, it means we can't go any
        // further back in the pages, so we will render a disabled previous button
        // when that is the case. Otherwise, we will give it an active "status".
        if ($this->currentPage <= 1)
        {
            return '<li class="allow unavailable"><span>'.$text.'</span></li>';
        }
        else
        {
            $url = $this->paginator->getUrl($this->currentPage - 1);

            return '<li class="allow"><a href="'.$url.'">'.$text.'</a></li>';
        }
    }

    /**
     * Get the next page pagination element.
     *
     * @param  string  $text
     * @return string
     */
    public function getNext($text = '&raquo;')
    {
        // If the current page is greater than or equal to the last page, it means we
        // can't go any further into the pages, as we're already on this last page
        // that is available, so we will make it the "next" link style disabled.
        if ($this->currentPage >= $this->lastPage)
        {
            return '<li class="allow unavailable"><span>'.$text.'</span></li>';
        }
        else
        {
            $url = $this->paginator->getUrl($this->currentPage + 1);

            return '<li class="allow"><a href="'.$url.'">'.$text.'</a></li>';
        }
    }

    /**
     * Get a pagination "dot" element.
     *
     * @return string
     */
    public function getDots()
    {
        return '<li class="unavailable"><span>...</span></li>';
    }

    /**
     * Create a pagination slider link.
     *
     * @param  mixed   $page
     * @return string
     */
    public function getLink($page)
    {
        $url = $this->paginator->getUrl($page);

        return '<li><a href="'.$url.'">'.$page.'</a></li>';
    }

}

Illuminate\Pagination\BootstrapPresenterを拡張していますが、実際、このクラス内にハードコードされている、HTMLのclass指定をFoundation5用に書き換えているだけです。

このプレゼンテーターにはインターフェイスが定義されていません。ですから、自由に自分の好きなように作成してもかまいません。要は、ペジネーション用のコードを生成できれば良いわけです。(ですから、自作する場合は、別段renderというメソッド名にこだわる必要もありません。)

これで準備が整いました。app/config/view.phpを変更し、最初に作成した'pagination.foundation5`をビューとして指定してください。Laravel4が提供しているビューを利用する場合は'pagination::...'と書きますが、自前のビューを利用する場合は、いつもビューを指定している通りに指定します。

これで、ペギネーションを利用すれば、Foundation5用に表示されます。(実際は、Bootstrapと大して違いが出ないのですけど。:D)

注意

多分、Foundation5はリリースされたばかりで、結構バグがあるようです。例えばcssにはペジネーションのactiveクラスの属性指定がないため、現在のページがデモのように表示されません。

対応されるまで、自分で指定する必要があります。

ul.pagination li.current {
    background: none repeat scroll 0 0 #008CBA;
    color: #FFFFFF;
    cursor: default;
    font-weight: bold;
    padding: 0.05556rem 0.55556rem;
    border-radius: 3px;
}

ペギネーションはとても難しい問題を含んでいます。それは、ペギネーションと書くとペジネーション派の人から揶揄され、ペジネーションと書くとペギネーション派の人からブーブー言われます。願わくば、こんなことで突っ込まれないように…(最初のぺは、あの英語の時間に習ったアとエの中間という音です。その後はじぇじぇじぇのジェですから、ペジェネイションかパジェネイションが正しいと、自分で突っ込んでおきましょう。ペァジェネイションかな?)

明日の担当も、私です。明後日はまだ誰も予約していません。この程度、これより簡単でも、使用感の感想でも良いので、書きたい方はどうぞ。