ぽんこつエンジニアのブログ

PHP チョット デキル

【Laravel4】Paginationいじり

この記事はLaravel Advent Calendar 2014の14日目です。

初めましてichikawa0829です。

今日は偶然にも衆議院議員選挙の投票日ですね。私は朝一で投票してまいりました。皆様はすでに投票に行かれたでしょうか?まだの方は私の駄文を読み進める前に是非とも投票を!

ということで、14日目の今回はページャーについて書きます。

概要

言語やフレームワーク問わず何かと苦労する事の多いページャーですが、Laravelでは比較的簡単に書くことができます。 デフォルトでは2種類(厳密には3種類)simpleとslider-3が用意されていて、Bootstrap 3と互換性のあるHTMLを簡単に書き出す事ができます。

基本的な使い方はモデルからpaginationメソッドを呼び出してPaginatorをviewに渡してあげるようになるかと思います。

<?php

class PaginateController extends \BaseController
{
    public function simple()
    {
        $users = DB::table('users')->paginate(3);
        return View::make('pagination', [
            'users' => $users
        ]);
    }

    public function slider()
    {
        return View::make('pagination', [
            'users' => User::paginate(3)
        ]);
    }
}

使用するビューのタイプを切り替えるにはapp/config/view.phpのpaginationの値を変更します。

<?php
return array(
    'pagination' => 'pagination::simple',
);

※任意の場所でConfig::setで設定を変更することも可能です。

<?php
Config::set('view.pagination', 'pagination::slider');

Pagination Viewごとの違い

まずは、それぞれの違いを見ていくためにテンプレートファイルを用意します。

<!doctype html>
<html>
<head>
    <title>Laravel Advent Calender 2014.12.14</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
</head>

<body>
    <div class="container">
        <h1>Laravel Pagination!</h1>
        <div>
        <table class="table table-bordered">
            <tr>
                <th>id</th>
                <th>name</th>
            </tr>
            @foreach($users as $user)
                <tr>
                    <td>{{{$user->id}}}</td>
                    <td>{{{$user->name}}}</td>
                </tr>
            @endforeach
        </table>
        {{ $users->links() }}
        </div>
    </div>
</body>
</html>

simple

simpleはその名の通りシンプルなページャーで、「次へ」ボタンと「前へ」ボタンのみを出力します。

出力されるHTMLは以下のようになります。

 <ul class="pager">
    <li><a href="http://devlab.tokyo/paginate/simple?page=6" rel="prev">&laquo; Previous</a></li>
    <li class="disabled"><span>Next &raquo;</span></li>
</ul>

f:id:ichikawa0829:20141209230101p:plain

「前へ」・「次へ」リンクが生成されますが、app/lang/en/pagination.phpを編集して文言を変更することも可能です。

<?php
return array(
    'previous' => '← まえー',
    'next'     => 'つぎー →',
);

f:id:ichikawa0829:20141209231046p:plain

slider-3

こちらは現在のページを基準に前後数ページと「前へ」「次へ」のリンクを出力します。

<ul class="pagination">
    <li class="disabled"><span>&laquo;</span></li>
    <li class="active"><span>1</span></li>
    <li><a href="http://devlab.tokyo/paginate/slider3?page=2">2</a></li>
    <li><a href="http://devlab.tokyo/paginate/slider3?page=3">3</a></li>
    <li><a href="http://devlab.tokyo/paginate/slider3?page=4">4</a></li>
    <li><a href="http://devlab.tokyo/paginate/slider3?page=5">5</a></li>
    <li><a href="http://devlab.tokyo/paginate/slider3?page=6">6</a></li>
    <li><a href="http://devlab.tokyo/paginate/slider3?page=7">7</a></li>
    <li><a href="http://devlab.tokyo/paginate/slider3?page=2" rel="next">&raquo;</a></li>
</ul>

f:id:ichikawa0829:20141209230136p:plain

slider

こちらは表示するリンクはslider-3と同様ですが、出力するHTMLが若干異なり、Bootstrap 2に互換性があります。 Bootstrap 2のCSSを使用していれば表示はslider-3とほぼ同様です。

<div class="pagination">
    <ul>
        <li class="disabled"><span>&laquo;</span></li>
        <li class="active"><span>1</span></li>
        <li><a href="http://devlab.tokyo/paginate/slider?page=2">2</a></li>
        <li><a href="http://devlab.tokyo/paginate/slider?page=3">3</a></li>
        <li><a href="http://devlab.tokyo/paginate/slider?page=4">4</a></li>
        <li><a href="http://devlab.tokyo/paginate/slider?page=5">5</a></li>
        <li><a href="http://devlab.tokyo/paginate/slider?page=6">6</a></li>
        <li><a href="http://devlab.tokyo/paginate/slider?page=7">7</a></li>
        <li><a href="http://devlab.tokyo/paginate/slider?page=2" rel="next">&raquo;</a></li>
    </ul>
</div>

※参考 http://getbootstrap.com/2.3.2/components.html#pagination

ページャーをカスタムする方法

Bootstrapと同じようなタグ構成・CSSに出来れば話は簡単なのですが、実際使う場合は様々な大人の事情によりそうもいかない場合が多いと思います。

そんな場合はかカスタムプレゼンターを作成してページャをカスタムしましょう。

\Illuminate\Pagination\Presenterを継承したクラスを作成し、以下の3つのabstractメソッドを実装すれば基本は完了です。

  • getPageLinkWrapper()
  • getDisabledTextWrapper()
  • getActivePageWrapper()
<?php
class CustomPresenter extends \Illuminate\Pagination\Presenter
{
    public function getPageLinkWrapper($url, $page, $rel = null)
    {
        return '<td><a href="' . $url . '">' . $page . '</a></td>';
    }

    public function getDisabledTextWrapper($text)
    {
        return '<td class="disabled">' . $text . '</td>';
    }

    public function getActivePageWrapper($text)
    {
        return  '<td class="current">'.$text.'</td>';
    }
}

カスタムプレゼンタを使用する場合は以下のようにPaginatorを引数にnewしてあげます。

<?php
class PaginateController extends \BaseController
{
    public function custom()
    {
        $users = DB::table('users')->paginate(3);
        return View::make('pagination_custom', [
            'users' => $users,
            'presenter' => new CustomPresenter($users)
        ]);
    }
}

paginateは<ul></ul>まで出力してくれていましたがカスタムプレゼンタはrenderをオーバーライドして改良しない限りは「前へ」、「各ページへ」、「次へ」のリンクしか出力してくれないので必要な場合はviewに記述しておきます。

<!doctype html>
<html>
<head>
    <title>Laravel Advent Calender 2014.12.14</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
</head>

<body>
    <div class="container">
        <h1>Laravel Pagination!</h1>
        <div>
        <table class="table table-bordered">
            <tr>
                <th>id</th>
                <th>name</th>
            </tr>
            @foreach($users as $user)
                <tr>
                    <td>{{{$user->id}}}</td>
                    <td>{{{$user->name}}}</td>
                </tr>
            @endforeach
        </table>
        <table>
            {{ $presenter->render() }}
        </table>
        </div>
    </div>
</body>
</html>

Presenterには他にもrender()、getPageSlider()、getAdjacentRange()などを改良することで表示されるページのレンジを変えたりとか、getDots()を変更してページ数が多くなった時に表示される「...」の部分を変更したりとか色々変更可能です。もっとここ変更したいんだって方はIlluminate\Pagination\Presenterを覗いてみるといいかもしれません。

明日はABCanG1015さんの「Markdownで管理できるポータルサイト自作した話」です。