1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 20854 -->
4 <sect1 id="zend.paginator.usage">
7 <sect2 id="zend.paginator.usage.paginating">
8 <title>データコレクションのページ処理</title>
11 ページ処理を行うには、<classname>Zend_Paginator</classname>
12 がデータにアクセスするための汎用的な方法が必要です。
13 そのため、データへのアクセスはすべてデータソースアダプタを用いて行います。
14 Zend Framework には、いくつかのアダプタが標準で同梱されています。
17 <table id="zend.paginator.usage.paginating.adapters">
18 <title>Zend_Paginator 用のアダプタ</title>
30 <entry><acronym>PHP</acronym> の配列を使用します。</entry>
33 <entry>DbSelect</entry>
35 <link linkend="zend.db.select"><classname>Zend_Db_Select</classname></link>
40 <entry>DbTableSelect</entry>
42 <link linkend="zend.db.table.fetch-all"><classname>Zend_Db_Table_Select</classname></link>
44 <classname>Zend_Db_Table_Rowset_Abstract</classname>
51 <entry>Iterator</entry>
53 <ulink url="http://www.php.net/~helly/php/ext/spl/interfaceIterator.html"><classname>Iterator</classname></ulink>
60 データのページ処理を管理する際に <classname>Zend_Paginator</classname>
61 を使用しません。その場合でもページ処理コントロールの機能を使うことはできます。
70 指定したクエリにマッチするすべての行を取得するのではなく、
71 DbSelect アダプタや DbTableSelect アダプタは
72 現在のページの表示のための必要最小限のデータのみを取得します。
76 そのため、マッチする行の総数を得るための別のクエリが動的に生成されます。
77 しかし、総数を直接指定したり、総数を求めるクエリを直接指定したりすることもできます。
79 <methodname>setRowCount()</methodname> メソッドを参照ください。
84 <classname>Zend_Paginator</classname> のインスタンスを作成するには、
85 コンストラクタでアダプタを指定しなければなりません。
88 <programlisting language="php"><![CDATA[
89 $paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($array));
93 利便性を確保するために、Zend Framework に同梱されているアダプタ用の静的メソッド
94 <methodname>factory()</methodname> も用意されています。
97 <programlisting language="php"><![CDATA[
98 $paginator = Zend_Paginator::factory($array);
103 <classname>Null</classname> アダプタの場合は、
104 データコレクションのかわりに要素数をコンストラクタで指定します。
109 この状態でも技術的には既に使用可能ですが、
110 ユーザが要求したページ番号をコントローラのアクション内で教えてやる必要があります。
111 これにより、データを読み進めていくことが可能となります。
114 <programlisting language="php"><![CDATA[
115 $paginator->setCurrentPageNumber($page);
119 ページ番号は <acronym>URL</acronym> で指定するのがもっともシンプルな方法でしょう。
120 <classname>Zend_Controller_Router_Interface</classname>
126 <acronym>INI</acronym> ファイルで定義するルートの例を次に示します。
129 <programlisting language="php"><![CDATA[
130 routes.example.route = articles/:articleName/:page
131 routes.example.defaults.controller = articles
132 routes.example.defaults.action = view
133 routes.example.defaults.page = 1
134 routes.example.reqs.articleName = \w+
135 routes.example.reqs.page = \d+
139 この設定を使った (そして Zend Framework の <acronym>MVC</acronym> コンポーネントを使った)
140 場合、現在のページ番号を設定するコードはこのようになります。
143 <programlisting language="php"><![CDATA[
144 $paginator->setCurrentPageNumber($this->_getParam('page'));
149 <link linkend="zend.paginator.configuration">設定</link>
154 最後に、paginator のインスタンスをビューに割り当てます。
155 <classname>Zend_View</classname> と ViewRenderer アクションヘルパーを使っている場合は、
159 <programlisting language="php"><![CDATA[
160 $this->view->paginator = $paginator;
164 <sect2 id="zend.paginator.usage.dbselect">
165 <title>DbSelect および DbTableSelect アダプタ</title>
167 大半のアダプタの使用法は非常にわかりやすいものです。
169 データベースからのデータの取得方法や件数の数え方についてのより詳細な説明が必要です。
173 DbSelect アダプタや DbTableSelect アダプタを使う際には、
174 事前にデータベースからデータを取得する必要はありません。
175 どちらのアダプタも、自動的にデータを取得して総ページ数を計算します。
176 もしデータベースからのデータに対して何らかの処理が必要となるのなら、
177 アダプタの <methodname>getItems()</methodname> メソッドをアプリケーション内で継承します。
182 数を数える際にデータベースの全レコードを取得するわけでは
183 <emphasis>ありません</emphasis>。そのかわりに、アダプタが元のクエリを修正し、
184 それに対応する COUNT クエリを作成します。
185 Paginator は、その COUNT クエリを実行して行数を取得するのです。
186 そのぶんデータベースとの余分なやりとりが必要となりますが、結果セット全体を取得して
187 <methodname>count()</methodname> を使うよりは何倍も高速になります。
188 大量のデータを扱う場合などは特にそうです。
192 データベースアダプタは、すべてのモダンなデータベース上で実行できる
193 もっとも効率的なクエリを作成しようとします。
194 しかし、使用するデータベースやスキーマ設定によっては
195 行数を取得するのにもっと効率的な方法があるかもしれません。
196 そのような場合のために、データベースアダプタでは独自の COUNT
197 クエリを設定できるようにもなっています。たとえば、
198 別々のテーブルにある blog の投稿の数を調べるには、
199 次の用に設定すればより高速な count クエリが使用できるでしょう。
202 <programlisting language="php"><![CDATA[
203 $adapter = new Zend_Paginator_Adapter_DbSelect($db->select()->from('posts'));
204 $adapter->setRowCount(
209 Zend_Paginator_Adapter_DbSelect::ROW_COUNT_COLUMN => 'post_count'
214 $paginator = new Zend_Paginator($adapter);
218 この方法は、小規模なデータや単純な select クエリの場合にはあまり劇的な効果を得られません。
219 しかし、複雑なクエリや大規模なデータを扱う場合は
220 かなりパフォーマンスが向上することでしょう。
224 <sect2 id="zend.paginator.rendering">
225 <title>ビュースクリプトによるページのレンダリング</title>
228 ビュースクリプトを使用してページ項目のレンダリング
229 (<classname>Zend_Paginator</classname> を使うよう設定している場合)
230 とページ処理コントロールの表示を行います。
234 <classname>Zend_Paginator</classname> は <acronym>SPL</acronym> の
235 <ulink url="http://www.php.net/~helly/php/ext/spl/interfaceIteratorAggregate.html"><classname>IteratorAggregate</classname></ulink>
237 項目を順次処理したり表示したりするのは簡単です。
240 <programlisting language="php"><![CDATA[
244 <?php if (count($this->paginator)): ?>
246 <?php foreach ($this->paginator as $item): ?>
247 <li><?php echo $item; ?></li>
252 <?php echo $this->paginationControl($this->paginator,
254 'my_pagination_control.phtml'); ?>
260 最後のほうでビューヘルパーをコールしているところに注目しましょう。
261 PaginationControl 4 つまでのパラメータを受け取ります。
262 paginator のインスタンス、スクロール形式、
267 2 番目と 3 番目のパラメータは重要です。
268 ビュー partial はページ処理コントロールの
269 <emphasis>見た目</emphasis>を決めるために用いられ、
270 一方スクロール形式はその <emphasis>振る舞い</emphasis>
271 を決めるために用いられます。ビュー partial
272 が、次のようなページ処理コントロール形式だっととしましょう。
276 <inlinegraphic align="center" valign="middle"
277 fileref="figures/zend.paginator.usage.rendering.control.png"
282 ここで "next" リンクを数回クリックしたときに、いったい何が起こるでしょう?
284 クリックし続けても現在のページがずっと中央に表示される (Yahoo!
286 表示される範囲はそのままで現在のページの位置がどんどん右にずれていき、
287 表示範囲の最後をページでさらに "next" をクリックしたときに一番左に戻るかもしれません。
288 ページを進めるたびにページ数そのものが増加 ("scroll")
289 していく (Google 形式) も考えられます。
293 4 種類のスクロール形式が Zend Framework に組み込まれています。
296 <table id="zend.paginator.usage.rendering.scrolling-styles">
297 <title>Zend_Paginator のスクロール形式</title>
302 <entry>スクロール形式</entry>
312 ドロップダウンメニュー形式でページ選択をさせる際に便利です。
313 そのような場合は、利用できるすべてのページを
318 <entry>Elastic</entry>
321 ユーザがページを移動するのにあわせて拡大・縮小します。
325 <entry>Jumping</entry>
328 ページ番号が表示範囲の最後に向けて進んでいきます。
329 表示範囲を超えると、新しい範囲の最初の位置に移動します。
333 <entry>Sliding</entry>
336 現在表示されているページが常にページ範囲の中央
338 にあるようにします。これがデフォルトの形式です。
346 4 番目、そして最後のパラメータはオプションの連想配列です。
347 ここで、ビューパーシャルから (<varname>$this</varname> を用いて)
349 たとえば、ページ移動用のリンクに使用する追加の
350 <acronym>URL</acronym> パラメータなどを含めることができます。
354 デフォルトのビュー partial とスクロール形式、
355 そしてビューのインスタンスを設定してしまえば、
356 PaginationControl のコールを完全に除去できます。
359 <programlisting language="php"><![CDATA[
360 Zend_Paginator::setDefaultScrollingStyle('Sliding');
361 Zend_View_Helper_PaginationControl::setDefaultViewPartial(
362 'my_pagination_control.phtml'
364 $paginator->setView($view);
370 文を使用するだけでページ処理コントロールをレンダリングできるようになります。
373 <programlisting language="php"><![CDATA[
374 <?php echo $this->paginator; ?>
379 もちろん、<classname>Zend_Paginator</classname>
380 を別のテンプレートエンジンで使用することもできます。
381 たとえば、Smarty を使用する場合は次のようになります。
384 <programlisting language="php"><![CDATA[
385 $smarty->assign('pages', $paginator->getPages());
389 そして、テンプレートからは次のようにして paginator の値にアクセスします。
392 <programlisting language="php"><![CDATA[
397 <sect3 id="zend.paginator.usage.rendering.example-controls">
398 <title>ページ処理コントロールの例</title>
402 とりあえず使い始めるにあたっての参考となることでしょう。
409 <programlisting language="php"><![CDATA[
411 See http://developer.yahoo.com/ypatterns/pattern.php?pattern=searchpagination
414 <?php if ($this->pageCount): ?>
415 <div class="paginationControl">
417 <?php if (isset($this->previous)): ?>
418 <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
422 <span class="disabled">< Previous</span> |
426 <?php foreach ($this->pagesInRange as $page): ?>
427 <?php if ($page != $this->current): ?>
428 <a href="<?php echo $this->url(array('page' => $page)); ?>">
432 <?php echo $page; ?> |
437 <?php if (isset($this->next)): ?>
438 <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
442 <span class="disabled">Next ></span>
452 <programlisting language="php"><![CDATA[
454 See http://developer.yahoo.com/ypatterns/pattern.php?pattern=itempagination
457 <?php if ($this->pageCount): ?>
458 <div class="paginationControl">
459 <?php echo $this->firstItemNumber; ?> - <?php echo $this->lastItemNumber; ?>
460 of <?php echo $this->totalItemCount; ?>
463 <?php if (isset($this->previous)): ?>
464 <a href="<?php echo $this->url(array('page' => $this->first)); ?>">
468 <span class="disabled">First</span> |
472 <?php if (isset($this->previous)): ?>
473 <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
477 <span class="disabled">< Previous</span> |
481 <?php if (isset($this->next)): ?>
482 <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
486 <span class="disabled">Next ></span> |
490 <?php if (isset($this->next)): ?>
491 <a href="<?php echo $this->url(array('page' => $this->last)); ?>">
495 <span class="disabled">Last</span>
506 <programlisting language="php"><![CDATA[
507 <?php if ($this->pageCount): ?>
508 <select id="paginationControl" size="1">
509 <?php foreach ($this->pagesInRange as $page): ?>
510 <?php $selected = ($page == $this->current) ? ' selected="selected"' : ''; ?>
512 echo $this->url(array('page' => $page));?>"<?php echo $selected ?>>
519 <script type="text/javascript"
520 src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js">
522 <script type="text/javascript">
523 $('paginationControl').observe('change', function() {
524 window.location = this.options[this.selectedIndex].value;
530 <sect3 id="zend.paginator.usage.rendering.properties">
531 <title>プロパティの一覧</title>
534 次のオプションが、ページ処理コントロールのビュー
538 <table id="zend.paginator.usage.rendering.properties.table">
539 <title>ビュー partial のプロパティ</title>
552 <entry>integer</entry>
553 <entry>最初のページ番号 (つまり 1)</entry>
556 <entry>firstItemNumber</entry>
557 <entry>integer</entry>
563 <entry>firstPageInRange</entry>
564 <entry>integer</entry>
566 スクロール形式で返された範囲内の最初のページ
570 <entry>current</entry>
571 <entry>integer</entry>
572 <entry>現在のページ番号</entry>
575 <entry>currentItemCount</entry>
576 <entry>integer</entry>
577 <entry>このページの項目の数</entry>
580 <entry>itemCountPerPage</entry>
581 <entry>integer</entry>
582 <entry>各ページに表示できる項目の最大数</entry>
586 <entry>integer</entry>
587 <entry>最後のページ番号</entry>
590 <entry>lastItemNumber</entry>
591 <entry>integer</entry>
597 <entry>lastPageInRange</entry>
598 <entry>integer</entry>
600 スクロール形式で返された範囲内の最後のページ
605 <entry>integer</entry>
606 <entry>次のページ番号</entry>
609 <entry>pageCount</entry>
610 <entry>integer</entry>
614 <entry>pagesInRange</entry>
621 <entry>previous</entry>
622 <entry>integer</entry>
623 <entry>前のページ番号</entry>
626 <entry>totalItemCount</entry>
627 <entry>integer</entry>