ページング処理
表示データのページング
例えば通販サイトの商品リスト表示のように、大量のデータを表示する場合、全てをページ内に表示するのは現実的ではありません。
そのためにページ分けし、1ページに表示するデータの数を制限するのが一般的です。
Curryではこれを簡単に実現する機能を備えたPagerクラスが用意されています。
Pagerクラスは、データ総数と1ページの表示件数を設定する事で、ページ数を計算し、以下のような、ページナビゲータのHTMLソースを生成します。
Pagerクラス
Pagerクラスの基本的な利用方法は以下のような感じです。
public function listAction() { // データ総数取得 $product = $this->model('Product'); $cnt = $product->getTotalCount(); $limit = 10; Loader::load('Pager', 'utility'); $pager = new Pager(); // リンクURL設定 $pager->setUrl($this->request->getPath() . '/?p=%page%'); // 現在ページ設定 $pager->setCurrentPage($this->request->getQuery('p')); // データ総数設定 $pager->setDataCount($cnt); // 1ページ表示件数設定 $pager->setCountPerPage($limit); // ページ計算処理実行 $pager->paginate(); // ビューへページャーを設定 $this->view->pager = $pager; // 現在ページの表示データ取得 $offset = $pager->getDataOffset(); $products = $model->getData($limit, $offset); $this->view->products = $products; }
{$pager->outputTag()}
基本的にはPagerクラスのインスタンスを生成し、paginateメソッドでページ計算を行いますが、事前に行なっている4つの設定メソッドの実行が必要です。
setCountPerPageはデフォルトが10なので、10で良い場合は設定の必要はありません。
そしてインスタンスをそのままビューに設定し、ビューテンプレートでoutputTagメソッドを実行すれば、ページナビゲーターのHTMLが出力されます。
また、Pagerの設定には以下の様な方法もあります。
$pager = new Pager();
// リクエストオブジェクトを設定
$pager->setRequest($this->request);
// データ総数設定
$pager->setDataCount($cnt);
// 1ページ表示件数設定
$pager->setCountPerPage($limit);
// ページ計算処理実行
$pager->paginate();
setRequestでRequestクラスのインスタンスを設定すると、リクエスト情報をもとにsetUrlとsetCurrentPageが自動的に実行され、URLと現在ページが設定されます。
setUrlメソッドとsetCurrentPageメソッドを明示的に実行する場合は、ページのパラメータクエリキーを指定することができますが、setRequestで行った場合、このキーは"p"に固定されます。
特にこだわりがない場合はsetRequestメソッドを利用することで処理を簡素化することができるわけです。
ページナビゲータのカスタマイズ
出力されるページナビゲータは単純なHTMLなので、見栄えはスタイルシートによって調整可能ですが、デフォルトでは上記のようなシンプルなものです。
デフォルトでは出力されるHTMLは以下の様なものです。
<div class="pager"> <span class="page"><a href="/controller/action/?p=1"><<</a></span> <span class="page"><a href="/controller/action/?p=5"><</a></span> <span class="page"><a href="/controller/action/?p=1">1</a></span> <span class="page"><a href="/controller/action/?p=2">2</a></span> <span class="page"><a href="/controller/action/?p=3">3</a></span> <span class="page"><a href="/controller/action/?p=4">4</a></span> <span class="page"><a href="/controller/action/?p=5">5</a></span> <span class="page">6</span> <span class="page"><a href="/controller/action/?p=7">7</a></span> <span class="page"><a href="/controller/action/?p=8">8</a></span> <span class="page"><a href="/controller/action/?p=9">9</a></span> <span class="page"><a href="/controller/action/?p=10">10</a></span> <span class="page"><a href="/controller/action/?p=7">></a></span> <span class="page"><a href="/controller/action/?p=10">>></a></span> </div>
"pager"というクラスの大枠と、"page"という各ページのリンクのタグによって構成されます。
更に各ページのタグは、ページ番号部分と、「先頭へ」「前へ」「後ろへ」「最後へ」を表す部分に分類されます。
このそれぞれのタグの種類とスタイル、表示文字はカスタマイズが可能です。
カスタマイズにはsetOutputOptionメソッドを利用します。
例えば各ページのタグをdivにし、ボーダーで囲むような形式にするには以下のようにします。
$pager->setOutputOption(array( 'top_tag' => 'div', 'last_tag' => 'div', 'prev_tag' => 'div', 'next_tag' => 'div', 'page_tag' => 'div' ));
<style tyle="text/css">
.pager {
overflow: hidden;
}
.pager div.page {
float: left;
margin: 0 3px;
padding: 5px;
border: 1px solid #cccccc;
}
</style>
{$pager->outputTag()}
次の例は、ページ番号を括弧"[ ]"で囲み、先頭・最後・前・次の文字を変更する指定方法です。
$pager->setOutputOption(array( 'page_format' => '[%page%]', 'top_text' => '先頭', 'last_text' => '最後', 'prev_text' => '前', 'next_text' => '次' ));
また、外枠のタグと、各ページのタグ、先頭・最後・前・次の各タグは、それぞれタグのクラスやスタイルを任意に指定することが可能です。
デフォルトは外枠が"pager"、各ページ等は"page"になっています。
例えば外枠のクラスを"custom_pager"、各ページを"custom_page"、先頭・最後・前・次は"jump"というクラスに設定し、先頭・最後はstyle属性を直接指定したい場合は以下のようにします。
$pager->setOutputOption(array( 'frame_class' => 'custom_pager', 'page_class' => 'custom_page', 'top_class' => 'jump', 'top_style' => 'font-weight:bolder;', 'last_class' => 'jump', 'last_style' => 'font-weight:bolder;', 'prev_class' => 'jump', 'next_class' => 'jump' ));
この場合の出力HTMLは以下のようになります。
<div class="custom_pager"> <span class="jump" style="font-weight:bolder;"><a href="/controller/action/?p=1"><<</a></span> <span class="jump"><a href="/controller/action/?p=5"><</a></span> <span class="custom_page"><a href="/controller/action/?p=1">1</a></span> <span class="custom_page"><a href="/controller/action/?p=2">2</a></span> <span class="custom_page"><a href="/controller/action/?p=3">3</a></span> <span class="custom_page"><a href="/controller/action/?p=4">4</a></span> <span class="custom_page"><a href="/controller/action/?p=5">5</a></span> <span class="custom_page">6</span> <span class="custom_page"><a href="/controller/action/?p=7">7</a></span> <span class="custom_page"><a href="/controller/action/?p=8">8</a></span> <span class="custom_page"><a href="/controller/action/?p=9">9</a></span> <span class="custom_page"><a href="/controller/action/?p=10">10</a></span> <span class="jump"><a href="/controller/action/?p=7">></a></span> <span class="jump" style="font-weight:bolder;"><a href="/controller/action/?p=10">>></a></span> </div>
指定できるオプションは以下のとおりです。
| キー | 内容 | デフォルト |
|---|---|---|
| frame_tag | ナビゲータ領域の外枠ボックス領域のタグを指定します。 | div |
| frame_class | ナビゲータ領域の外枠ボックス領域のタグのクラスを指定します。 | pager |
| page_tag | 各ページの領域のタグを指定します。 | span |
| page_class | 各ページの領域のタグのクラスを指定します。 | page |
| page_style | 各ページの領域のスタイルシートを指定します。 | |
| page_format | 各ページの表示文字のフォーマットを指定します。%page%をプレースホルダとして、実際の出力ではこの部分がページ番号に置き換わります。 | %page% |
| prev_tag | 「前のページ」を表すリンクのボックス領域のタグを指定します。 | span |
| prev_class | 「前のページ」を表すリンクのボックス領域のタグのクラスを指定します。 | page |
| prev_style | 「前のページ」を表すリンクのボックス領域のスタイルシートを指定します。 | |
| prev_text | 「前のページ」を表すリンクの表示文字を指定します。 | > |
| next_tag | 「次のページ」を表すリンクのボックス領域のタグを指定します。 | span |
| next_class | 「次のページ」を表すリンクのボックス領域のタグのクラスを指定します。 | page |
| next_style | 「次のページ」を表すリンクのボックス領域のスタイルシートを指定します。 | |
| next_text | 「次のページ」を表すリンクの表示文字を指定します。 | < |
| top_tag | 「最初のページ」を表すリンクのボックス領域のタグを指定します。 | span |
| top_class | 「最初のページ」を表すリンクのボックス領域のタグのクラスを指定します。 | page |
| top_style | 「最初のページ」を表すリンクのボックス領域のスタイルシートを指定します。 | |
| top_text | 「最初のページ」を表すリンクの表示文字を指定します。 | << |
| last_tag | 「最後のページ」を表すリンクのボックス領域のタグを指定します。 | span |
| last_class | 「最後のページ」を表すリンクのボックス領域のタグのクラスを指定します。 | page |
| last_style | 「最後のページ」を表すリンクのボックス領域のスタイルシートを指定します。 | |
| last_text | 「最後のページ」を表すリンクの表示文字を指定します。 | >> |
ページナビゲータのタグを自作する
タグの生成はoutputTagメソッドによって簡単に行うことができ、見栄えの調整も、setOutputメソッドとスタイルシートの組み合わせにより自由に行えますが、ビューテンプレートで自分でタグを記述することで、更に自由度の高いものとすることができます。
このためにはoutputTagは利用せず、getPageInfoメソッドによって得たページ情報を利用して、ビューテンプレートでタグを記述します。
$pager = new Pager();
$pager->setRequest($this->request);
$pager->setDataCount($cnt);
$pager->setCountPerPage($limit);
$pager->paginate();
// ページ情報取得
$pageInfo = $pager->getPageInfo();
$this->view->page_info = $pageInfo ;
<div class="pager"> <div class="page"> {if $page_info.top.url != ''}<a href="{$page_info.top.url}">最初へ</a>{else}最初へ{/if} </div> <div class="page"> {if $page_info.prev.url != ''}<a href="{$page_info.prev.url}">前へ</a>{else}前へ{/if} </div> {foreach from=$page_info.pages item=page} <div class="page"> {if $page.url != ''}<a href="{$page.url}">{$page.page}</a>{else}{$page.page}{/if} </div> {/foreach} <div class="page"> {if $page_info.next.url != ''}<a href="{$page_info.next.url}">次へ</a>{else}次へ{/if} </div> <div class="page"> {if $page_info.last.url != ''}<a href="{$page_info.last.url}">最後へ</a>{else}最後へ{/if} </div> </div>
getPageInfoメソッドによって得られる配列情報は以下の様な構造になっています。
array(
'top' => array(
'url' => 'http://・・・・?p=1'
),
'last' => array(
'url' => 'http://・・・・?p=5'
),
'prev' => array(
'url' => 'http://・・・・?p=2'
),
'next' => array(
'url' => 'http://・・・・?p=4'
),
'pages' => array(
array(
'page' => 1,
'url' => 'http://・・・・?p=1'
),
array(
'page' => 2,
'url' => 'http://・・・・?p=2'
),
array(
'page' => 3,
'url' => 'http://・・・・?p=3'
),
array(
'page' => 4,
'url' => 'http://・・・・?p=4'
),
array(
'page' => 5,
'url' => 'http://・・・・?p=5'
)
)
);
この情報を利用し、ビューテンプレートでタグを記述することで、自由自在にページナビゲータを作ることが可能です。
ページ表示範囲の限定
通常、ページナビゲータは1ページ目から、存在する最後のページまでの物が表示されます。
しかし、ページ数が多く、全て表示するのが難しい場合があります。
こういった場合のために、表示する範囲を現在のページの前後に表示する数を制限することが可能です。例えばページ数が100だったとしても、表示ページ範囲数を5に設定すると、現在のページが10の時、5~15のみがページナビゲータとして表示されます。
これにはsetDisplayRangeメソッドを利用します。
$pager->setDisplayRange(5);