読者です 読者をやめる 読者になる 読者になる

10分ぐらいで学べるSymfony2 〜pager編〜

今回はSymfony2でpageを実装する際のやり方のメモとなります。
symfony1だとsfPager又はsfDoctrinePager オブジェクトが存在してpager機能を実装してたのですが
Symfony2だとそんな機能はコア機能にはないようです。
そこでPagerBundleというバンドルを利用してpager機能を実装しました。


(1)インストール
vender下にバンドルをインストールしてオートロードの設定をします。

# vender/bundles/MakerLabs下にインストールされます
$ vi deps
[PagerBundle]
    git=git://github.com/makerlabs/PagerBundle.git
    target=bundles/MakerLabs/PagerBundle

# インストール
$ php bin/vendors install

# オートロードの設定を記述
$ vi app/autoload.php
    'MakerLabs'        => __DIR__.'/../vendor/bundles',
$ vi app/AppKernel.php
    new MakerLabs\PagerBundle\MakerLabsPagerBundle(),

(2)データベースを利用しないページャ
データベースオブジェクトを利用しない形のページャの例

# ルーティング設定
$ vi src/Root/SiteBundle/Resources/config/routing.yml
information:
    pattern:  /information/{page}
    defaults: { _controller: RootSiteBundle:Information:index, page: 1 }

# コントローラでは100個のデータを25個づつページングする設定
$ vi src/Root/SiteBundle/Controller/InformationController.php
use MakerLabs\PagerBundle\Pager;
use MakerLabs\PagerBundle\Adapter\ArrayAdapter;

class InformationController extends Controller
{
    public function indexAction($page)
    {
        $array = range(1, 100);
        $adapter = new ArrayAdapter($array);
        $pager = new Pager($adapter, array('page' => $page, 'limit' => 25));

        return $this->render('RootSiteBundle:Information:index.html.twig', array(
            'pager' => $pager
        ));
    }
}

# 数字をそのまま出力します。
$ vi src/Root/SiteBundle/Resources/views/Information/index.html.twig 
{% if pager.isPaginable %}
   {{ paginate(pager, 'information') }}
{% endif %}
{% for item in pager.getResults %}
   <p>{{ item }}</p>
{% endfor %}

(3)データベースを利用したページャ
次はデータをデータベースから取ってくる場合になります。

# AdapterをDoctrineOrmAdapterへ変更
$ vi src/Root/SiteBundle/Controller/InformationController.php
use MakerLabs\PagerBundle\Adapter\DoctrineOrmAdapter;

class InformationController extends Controller
{
    public function indexAction($page)
    {
        $em = $this->getDoctrine()->getEntityManager();
        $qb = $em->getRepository('RootSiteBundle:Information')->createQueryBuilder('f');
        $adapter = new DoctrineOrmAdapter($qb);
        $pager = new Pager($adapter, array('page' => $page, 'limit' => 5));

        return $this->render('RootSiteBundle:Information:index.html.twig', array(
            'pager' => $pager
        ));
    }

# Infomartionテーブルのtitleを表示
$ vi src/Root/SiteBundle/Resources/views/Information/index.html.twig
{% if pager.isPaginable %}
   {{ paginate(pager, 'information') }}
{% endif %}
{% for item in pager.getResults %}
   <p>{{ item.title }}</p>
{% endfor %}


(4)データベースからのSQLをカスタマイズ
(3)では無条件で取得していますが、informationテーブルにはstart_dateカラムがあり、
掲載開始前のデータは省く必要があります。
そんな時のSQLをカスタマイズはQueryBuilderを使用します

$ vi src/Root/SiteBundle/Controller/InformationController.php
        $now = date('Y-m-d H:i:s');
        $em = $this->getDoctrine()->getEntityManager();
        $qb = $em->getRepository('RootSiteBundle:Information')->createQueryBuilder('i')
                    ->where('i.start_date < :start_date')
                    ->setParameter('start_date', $now)
                    ->orderBy('i.start_date', 'DESC');
        $adapter = new DoctrineOrmAdapter($qb);
        $pager = new Pager($adapter, array('page' => $page, 'limit' => 5));

        return $this->render('RootSiteBundle:Information:index.html.twig', array(
            'pager' => $pager
        ));

(5)表示をカスタマイズ
次ページとかpaginate部分の表示をカスタマイズしたい場合はテンプレートを修正します。

# paginate.html.twigを読込するように指定
$ vi src/Root/SiteBundle/Resources/views/Information/index.html.twig
{% if pager.isPaginable %}
   {{ paginate(pager, 'information', {}, 'RootSiteBundle:Information:paginate.html.twig')) }}
{% endif %}
{% for item in pager.getResults %}
   <p>{{ item.title }}</p>
{% endfor %}

# これをベースに修正していきます
$ vi src/Root/SiteBundle/Resources/views/Information/paginate.html.twig
hoge
<ul class="pager">
   {% if pager.isFirstPage == false %}
        <li class="first"><a href="{{ paginate_path(route, pager.getFirstPage, parameters) }}">&laquo;</a></li>
        <li class="previous"><a href="{{ paginate_path(route, pager.getPreviousPage, parameters) }}">&lsaquo;</a></li>
   {% endif %}
   {% for page in pager.getPages %}
      {% if page == pager.getPage %}
        <li class="selected">
            <b>{{ page }}</b>
        </li>
      {% else %}
        <li>
            <a href="{{ paginate_path(route, page, parameters) }}">{{ page }}</a>
        </li>
      {% endif %}
   {% endfor %}
   {% if pager.isLastPage == false %}
        <li class="next"><a href="{{ paginate_path(route, pager.getNextPage, parameters) }}">&rsaquo;</a></li>
        <li class="last"><a href="{{ paginate_path(route, pager.getLastPage, parameters) }}">&raquo;</a></li>
   {% endif %}
</ul>

参考
pagerバンドルのページ
http://symfony2bundles.org/makerlabs/PagerBundle

以上です。