ページ処理を行うには、Zend_Paginator
がデータにアクセスするための汎用的な方法が必要です。
そのため、データへのアクセスはすべてデータソースアダプタを用いて行います。
Zend Framework には、いくつかのアダプタが標準で同梱されています。
表 36.1. Zend_Paginator 用のアダプタ
| アダプタ | 説明 |
|---|---|
| Array | PHP の配列を使用します。 |
| DbSelect |
Zend_Db_Select
のインスタンスを使用し、配列を返します。
|
| DbTableSelect |
Zend_Db_Table_Select
のインスタンスを使用し、
Zend_Db_Table_Rowset_Abstract
のインスタンスを返します。
これは、結果セットについての追加情報
(カラム名など) を提供します。
|
| Iterator |
Iterator
のインスタンスを使用します。
|
| Null |
データのページ処理を管理する際に Zend_Paginator
を使用しません。その場合でもページ処理コントロールの機能を使うことはできます。
|
![]() |
注意 |
|---|---|
|
指定したクエリにマッチするすべての行を取得するのではなく、 DbSelect アダプタや DbTableSelect アダプタは 現在のページの表示のための必要最小限のデータのみを取得します。
そのため、マッチする行の総数を得るための別のクエリが動的に生成されます。
しかし、総数を直接指定したり、総数を求めるクエリを直接指定したりすることもできます。
詳細な情報は、DbSelect アダプタの
|
Zend_Paginator のインスタンスを作成するには、
コンストラクタでアダプタを指定しなければなりません。
$paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($array));
利便性を確保するために、Zend Framework に同梱されているアダプタ用の静的メソッド
factory() も用意されています。
$paginator = Zend_Paginator::factory($array);
![]() |
注意 |
|---|---|
Null アダプタの場合は、 データコレクションのかわりに要素数をコンストラクタで指定します。 |
この状態でも技術的には既に使用可能ですが、 ユーザが要求したページ番号をコントローラのアクション内で教えてやる必要があります。 これにより、データを読み進めていくことが可能となります。
$paginator->setCurrentPageNumber($page);
ページ番号は URL で指定するのがもっともシンプルな方法でしょう。
Zend_Controller_Router_Interface
互換のルータを使うことを推奨しますが、
それが必須というわけではありません。
INI ファイルで定義するルートの例を次に示します。
routes.example.route = articles/:articleName/:page
routes.example.defaults.controller = articles
routes.example.defaults.action = view
routes.example.defaults.page = 1
routes.example.reqs.articleName = \w+
routes.example.reqs.page = \d+
この設定を使った (そして Zend Framework の MVC コンポーネントを使った) 場合、現在のページ番号を設定するコードはこのようになります。
$paginator->setCurrentPageNumber($this->_getParam('page'));
それ以外にもオプションがあります。詳細は 設定 を参照ください。
最後に、paginator のインスタンスをビューに割り当てます。
Zend_View と ViewRenderer アクションヘルパーを使っている場合は、
次のようになります。
$this->view->paginator = $paginator;
ビュースクリプトを使用してページ項目のレンダリング
(Zend_Paginator を使うよう設定している場合)
とページ処理コントロールの表示を行います。
Zend_Paginator は SPL の
IteratorAggregate
インターフェイスを実装しているので、
項目を順次処理したり表示したりするのは簡単です。
<html>
<body>
<h1>Example</h1>
<?php if (count($this->paginator)): ?>
<ul>
<?php foreach ($this->paginator as $item): ?>
<li><?= $item; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?= $this->paginationControl($this->paginator,
'Sliding',
'my_pagination_control.phtml'); ?>
</body>
</html>
最後のほうでビューヘルパーをコールしているところに注目しましょう。 PaginationControl 4 つまでのパラメータを受け取ります。 paginator のインスタンス、スクロール形式、 そして追加パラメータの配列です。
2 番目と 3 番目のパラメータは重要です。 ビュー partial はページ処理コントロールの 見た目を決めるために用いられ、 一方スクロール形式はその 振る舞い を決めるために用いられます。ビュー partial が、次のようなページ処理コントロール形式だっととしましょう。
ここで "next" リンクを数回クリックしたときに、いったい何が起こるでしょう? そう、いろんなことが起こりえます。 クリックし続けても現在のページがずっと中央に表示される (Yahoo! 形式) かもしれませんし、 表示される範囲はそのままで現在のページの位置がどんどん右にずれていき、 表示範囲の最後をページでさらに "next" をクリックしたときに一番左に戻るかもしれません。 ページを進めるたびにページ数そのものが増加 ("scroll") していく (Google 形式) も考えられます。
4 種類のスクロール形式が Zend Framework に組み込まれています。
表 36.2. Zend_Paginator のスクロール形式
| スクロール形式 | 説明 |
|---|---|
| All | すべてのページを返します。 総ページ数が比較的少なめのときなど、 ドロップダウンメニュー形式でページ選択をさせる際に便利です。 そのような場合は、利用できるすべてのページを 一度にユーザに見せることになるでしょう。 |
| Elastic | Google 風のスクロール形式で、 ユーザがページを移動するのにあわせて拡大・縮小します。 |
| Jumping | ユーザがページを進めるにつれて、 ページ番号が表示範囲の最後に向けて進んでいきます。 表示範囲を超えると、新しい範囲の最初の位置に移動します。 |
| Sliding | Yahoo! 風のスクロール形式で、 現在表示されているページが常にページ範囲の中央 (あるいは可能な限りそれに近い場所) にあるようにします。これがデフォルトの形式です。 |
4 番目、そして最後のパラメータはオプションの連想配列です。
ここで、ビューパーシャルから ($this を用いて)
使用したい追加変数を指定します。
たとえば、ページ移動用のリンクに使用する追加の
URL パラメータなどを含めることができます。
デフォルトのビュー partial とスクロール形式、 そしてビューのインスタンスを設定してしまえば、 PaginationControl のコールを完全に除去することができます。
Zend_Paginator::setDefaultScrollingStyle('Sliding');
Zend_View_Helper_PaginationControl::setDefaultViewPartial(
'my_pagination_control.phtml'
);
$paginator->setView($view);
これらの値をすべて設定すると、 ビュースクリプト内で単純な echo 文を使用するだけでページ処理コントロールをレンダリングできるようになります。
<?= $this->paginator; ?>
![]() |
注意 |
|---|---|
|
もちろん、
$smarty->assign('pages', $paginator->getPages());
そして、テンプレートからは次のようにして paginator の値にアクセスします。
{$pages.pageCount}
|
次のページ処理コントロールの例が、 とりあえず使い始めるにあたっての参考となることでしょう。
検索のページ処理
<!--
See http://developer.yahoo.com/ypatterns/pattern.php?pattern=searchpagination
-->
<?php if ($this->pageCount): ?>
<div class="paginationControl">
<!-- 前のページへのリンク -->
<?php if (isset($this->previous)): ?>
<a href="<?= $this->url(array('page' => $this->previous)); ?>">
< Previous
</a> |
<?php else: ?>
<span class="disabled">< Previous</span> |
<?php endif; ?>
<!-- ページ番号へのリンク -->
<?php foreach ($this->pagesInRange as $page): ?>
<?php if ($page != $this->current): ?>
<a href="<?= $this->url(array('page' => $page)); ?>">
<?= $page; ?>
</a> |
<?php else: ?>
<?= $page; ?> |
<?php endif; ?>
<?php endforeach; ?>
<!-- 次のページへのリンク -->
<?php if (isset($this->next)): ?>
<a href="<?= $this->url(array('page' => $this->next)); ?>">
Next >
</a>
<?php else: ?>
<span class="disabled">Next ></span>
<?php endif; ?>
</div>
<?php endif; ?>
項目のページ処理
<!--
See http://developer.yahoo.com/ypatterns/pattern.php?pattern=itempagination
-->
<?php if ($this->pageCount): ?>
<div class="paginationControl">
<?= $this->firstItemNumber; ?> - <?= $this->lastItemNumber; ?>
of <?= $this->totalItemCount; ?>
<!-- 最初のページへのリンク -->
<?php if (isset($this->previous)): ?>
<a href="<?= $this->url(array('page' => $this->first)); ?>">
First
</a> |
<?php else: ?>
<span class="disabled">First</span> |
<?php endif; ?>
<!-- 前のページへのリンク -->
<?php if (isset($this->previous)): ?>
<a href="<?= $this->url(array('page' => $this->previous)); ?>">
< Previous
</a> |
<?php else: ?>
<span class="disabled">< Previous</span> |
<?php endif; ?>
<!-- 次のページへのリンク -->
<?php if (isset($this->next)): ?>
<a href="<?= $this->url(array('page' => $this->next)); ?>">
Next >
</a> |
<?php else: ?>
<span class="disabled">Next ></span> |
<?php endif; ?>
<!-- 最後のページへのリンク -->
<?php if (isset($this->next)): ?>
<a href="<?= $this->url(array('page' => $this->last)); ?>">
Last
</a>
<?php else: ?>
<span class="disabled">Last</span>
<?php endif; ?>
</div>
<?php endif; ?>
ドロップダウンのページ処理
<?php if ($this->pageCount): ?>
<select id="paginationControl" size="1">
<?php foreach ($this->pagesInRange as $page): ?>
<?php $selected = ($page == $this->current) ? ' selected="selected"' : ''; ?>
<option value="<?= $this->url(array('page' => $page)); ?>"<?= $selected ?>>
<?= $page; ?>
</option>
<?php endforeach; ?>
</select>
<?php endif; ?>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js">
</script>
<script type="text/javascript">
$('paginationControl').observe('change', function() {
window.location = this.options[this.selectedIndex].value;
})
</script>
次のオプションが、ページ処理コントロールのビュー partial で使用可能です。
表 36.3. ビュー partial のプロパティ
| プロパティ | 型 | 説明 |
|---|---|---|
| first | integer | 最初のページ番号 (つまり 1) |
| firstItemNumber | integer | このページの最初の項目の番号 |
| firstPageInRange | integer | スクロール形式で返された範囲内の最初のページ |
| current | integer | 現在のページ番号 |
| currentItemCount | integer | このページの項目の数 |
| itemCountPerPage | integer | 各ページに表示できる項目の最大数 |
| last | integer | 最後のページ番号 |
| lastItemNumber | integer | このページの最後の項目の番号 |
| lastPageInRange | integer | スクロール形式で返された範囲内の最後のページ |
| next | integer | 次のページ番号 |
| pageCount | integer | ページ数 |
| pagesInRange | array | スクロール形式で返されたページの配列 |
| previous | integer | 前のページ番号 |
| totalItemCount | integer | 項目の総数 |