<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<!-- EN-Revision: 15103 -->
<sect1 id="zend.paginator.usage">
    <title>使用法</title>

    <sect2 id="zend.paginator.usage.paginating">
        <title>データコレクションのページ処理</title>

        <para>
            ページ処理を行うには、<classname>Zend_Paginator</classname>
            がデータにアクセスするための汎用的な方法が必要です。
            そのため、データへのアクセスはすべてデータソースアダプタを用いて行います。
            Zend Framework には、いくつかのアダプタが標準で同梱されています。
        </para>

        <table id="zend.paginator.usage.paginating.adapters">
            <title><classname>Zend_Paginator</classname> 用のアダプタ</title>

            <tgroup cols="2">
                <thead>
                    <row>
                        <entry>アダプタ</entry>
                        <entry>説明</entry>
                    </row>
                </thead>
                <tbody>
                    <row>
                        <entry>Array</entry>
                        <entry>PHP の配列を使用します。</entry>
                    </row>
                    <row>
                        <entry>DbSelect</entry>
                        <entry>
                            <link linkend="zend.db.select"><classname>Zend_Db_Select</classname></link>
                            のインスタンスを使用し、配列を返します。
                        </entry>
                    </row>
                    <row>
                        <entry>DbTableSelect</entry>
                        <entry>
                            <link linkend="zend.db.table.fetch-all"><classname>Zend_Db_Table_Select</classname></link>
                            のインスタンスを使用し、
                            <classname>Zend_Db_Table_Rowset_Abstract</classname>
                            のインスタンスを返します。
                            これは、結果セットについての追加情報
                            (カラム名など) を提供します。
                        </entry>
                    </row>
                    <row>
                        <entry>Iterator</entry>
                        <entry>
                            <ulink url="http://www.php.net/~helly/php/ext/spl/interfaceIterator.html"><code>Iterator</code></ulink>
                            のインスタンスを使用します。
                        </entry>
                    </row>
                    <row>
                        <entry>Null</entry>
                        <entry>
                            データのページ処理を管理する際に <classname>Zend_Paginator</classname>
                            を使用しません。その場合でもページ処理コントロールの機能を使うことはできます。
                        </entry>
                    </row>
                </tbody>
            </tgroup>
        </table>

        <note>
            <para>
                指定したクエリにマッチするすべての行を取得するのではなく、
                DbSelect アダプタや DbTableSelect アダプタは
                現在のページの表示のための必要最小限のデータのみを取得します。
            </para>

            <para>
                そのため、マッチする行の総数を得るための別のクエリが動的に生成されます。
                しかし、総数を直接指定したり、総数を求めるクエリを直接指定したりすることもできます。
                詳細な情報は、DbSelect アダプタの
                <code>setRowCount()</code> メソッドを参照ください。
            </para>
        </note>

        <para>
            <classname>Zend_Paginator</classname> のインスタンスを作成するには、
            コンストラクタでアダプタを指定しなければなりません。
        </para>

        <para>
            <programlisting role="php"><![CDATA[
$paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($array));
]]>
            </programlisting>
        </para>

        <para>
            利便性を確保するために、Zend Framework に同梱されているアダプタ用の静的メソッド
            <code>factory()</code> も用意されています。
        </para>

        <para>
            <programlisting role="php"><![CDATA[
$paginator = Zend_Paginator::factory($array);
]]>
            </programlisting>
        </para>

        <note>
            <para>
                Null アダプタの場合は、
                データコレクションのかわりに要素数をコンストラクタで指定します。
            </para>
        </note>

        <para>
            この状態でも技術的には既に使用可能ですが、
            ユーザが要求したページ番号をコントローラのアクション内で教えてやる必要があります。
            これにより、データを読み進めていくことが可能となります。
        </para>

        <para>
            <programlisting role="php"><![CDATA[
$paginator->setCurrentPageNumber($page);
]]>
            </programlisting>
        </para>

        <para>
            ページ番号は URL で指定するのがもっともシンプルな方法でしょう。
            <classname>Zend_Controller_Router_Interface</classname>
            互換のルータを使うことを推奨しますが、
            それが必須というわけではありません。
        </para>

        <para>
            INI ファイルで定義するルートの例を次に示します。
        </para>

        <para>
            <programlisting role="php"><![CDATA[
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+
]]>
            </programlisting>
        </para>

        <para>
            この設定を使った (そして Zend Framework の MVC コンポーネントを使った)
            場合、現在のページ番号を設定するコードはこのようになります。
        </para>

        <para>
            <programlisting role="php"><![CDATA[
$paginator->setCurrentPageNumber($this->_getParam('page'));
]]>
            </programlisting>
        </para>

        <para>
            それ以外にもオプションがあります。詳細は
            <link linkend="zend.paginator.configuration">設定</link>
            を参照ください。
        </para>

        <para>
            最後に、paginator のインスタンスをビューに割り当てます。
            <classname>Zend_View</classname> と ViewRenderer アクションヘルパーを使っている場合は、
            次のようになります。
        </para>

        <para>
            <programlisting role="php"><![CDATA[
$this->view->paginator = $paginator;
]]>
            </programlisting>
        </para>
    </sect2>

    <sect2 id="zend.paginator.rendering">
        <title>ビュースクリプトによるページのレンダリング</title>

        <para>
            ビュースクリプトを使用してページ項目のレンダリング
            (<classname>Zend_Paginator</classname> を使うよう設定している場合)
            とページ処理コントロールの表示を行います。
        </para>

        <para>
            <classname>Zend_Paginator</classname> は SPL の
            <ulink url="http://www.php.net/~helly/php/ext/spl/interfaceIteratorAggregate.html"><code>IteratorAggregate</code></ulink>
            インターフェイスを実装しているので、
            項目を順次処理したり表示したりするのは簡単です。
        </para>

        <para>
            <programlisting role="php"><![CDATA[
<html>
<body>
<h1>Example</h1>
<?php if (count($this->paginator)): ?>
<ul>
<?php foreach ($this->paginator as $item): ?>
  <li><?php echo $item; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>

<?php echo $this->paginationControl($this->paginator,
                             'Sliding',
                             'my_pagination_control.phtml'); ?>
</body>
</html>
]]>
            </programlisting>
        </para>

        <para>
            最後のほうでビューヘルパーをコールしているところに注目しましょう。
            PaginationControl 4 つまでのパラメータを受け取ります。
            paginator のインスタンス、スクロール形式、
            そして追加パラメータの配列です。
        </para>

        <para>
            2 番目と 3 番目のパラメータは重要です。
            ビュー partial はページ処理コントロールの
            <emphasis>見た目</emphasis>を決めるために用いられ、
            一方スクロール形式はその <emphasis>振る舞い</emphasis>
            を決めるために用いられます。ビュー partial
            が、次のようなページ処理コントロール形式だっととしましょう。
        </para>

        <para>
            <inlinegraphic align="center" valign="middle"
                fileref="figures/zend.paginator.usage.rendering.control.png"
                format="PNG"/>
        </para>

        <para>
            ここで "next" リンクを数回クリックしたときに、いったい何が起こるでしょう?
            そう、いろんなことが起こりえます。
            クリックし続けても現在のページがずっと中央に表示される (Yahoo!
            形式) かもしれませんし、
            表示される範囲はそのままで現在のページの位置がどんどん右にずれていき、
            表示範囲の最後をページでさらに "next" をクリックしたときに一番左に戻るかもしれません。
            ページを進めるたびにページ数そのものが増加 ("scroll")
            していく (Google 形式) も考えられます。
        </para>

        <para>
            4 種類のスクロール形式が Zend Framework に組み込まれています。
        </para>

        <table id="zend.paginator.usage.rendering.scrolling-styles">
            <title><classname>Zend_Paginator</classname> のスクロール形式</title>

            <tgroup cols="2">
                <thead>
                    <row>
                        <entry>スクロール形式</entry>
                        <entry>説明</entry>
                    </row>
                </thead>
                <tbody>
                    <row>
                        <entry>All</entry>
                        <entry>
                            すべてのページを返します。
                            総ページ数が比較的少なめのときなど、
                            ドロップダウンメニュー形式でページ選択をさせる際に便利です。
                            そのような場合は、利用できるすべてのページを
                            一度にユーザに見せることになるでしょう。
                        </entry>
                    </row>
                    <row>
                        <entry>Elastic</entry>
                        <entry>
                            Google 風のスクロール形式で、
                            ユーザがページを移動するのにあわせて拡大・縮小します。
                        </entry>
                    </row>
                    <row>
                        <entry>Jumping</entry>
                        <entry>
                            ユーザがページを進めるにつれて、
                            ページ番号が表示範囲の最後に向けて進んでいきます。
                            表示範囲を超えると、新しい範囲の最初の位置に移動します。
                        </entry>
                    </row>
                    <row>
                        <entry>Sliding</entry>
                        <entry>
                            Yahoo! 風のスクロール形式で、
                            現在表示されているページが常にページ範囲の中央
                            (あるいは可能な限りそれに近い場所)
                            にあるようにします。これがデフォルトの形式です。
                        </entry>
                    </row>
                </tbody>
            </tgroup>
        </table>

        <para>
            4 番目、そして最後のパラメータはオプションの連想配列です。
            ここで、ビューパーシャルから (<code>$this</code> を用いて)
            使用したい追加変数を指定します。
            たとえば、ページ移動用のリンクに使用する追加の
            URL パラメータなどを含めることができます。
        </para>

        <para>
            デフォルトのビュー partial とスクロール形式、
            そしてビューのインスタンスを設定してしまえば、
            PaginationControl のコールを完全に除去することができます。
        </para>

        <para>
            <programlisting role="php"><![CDATA[
Zend_Paginator::setDefaultScrollingStyle('Sliding');
Zend_View_Helper_PaginationControl::setDefaultViewPartial(
    'my_pagination_control.phtml'
);
$paginator->setView($view);
]]>
            </programlisting>
        </para>

        <para>
            これらの値をすべて設定すると、
            ビュースクリプト内で単純な echo
            文を使用するだけでページ処理コントロールをレンダリングできるようになります。
        </para>

        <para>
            <programlisting role="php"><![CDATA[
<?php echo $this->paginator; ?>
]]>
            </programlisting>
        </para>

        <note>
            <para>
                もちろん、<classname>Zend_Paginator</classname>
                を別のテンプレートエンジンで使用することもできます。
                たとえば、Smarty を使用する場合は次のようになります。
            </para>

            <para>
                <programlisting role="php"><![CDATA[
$smarty->assign('pages', $paginator->getPages());
]]>
                </programlisting>
            </para>

            <para>
                そして、テンプレートからは次のようにして paginator の値にアクセスします。
            </para>

            <para>
                <programlisting role="php"><![CDATA[
{$pages.pageCount}
]]>
                </programlisting>
            </para>
        </note>

        <sect3 id="zend.paginator.usage.rendering.example-controls">
            <title>ページ処理コントロールの例</title>

            <para>
                次のページ処理コントロールの例が、
                とりあえず使い始めるにあたっての参考となることでしょう。
            </para>

            <para>
                検索のページ処理

                <programlisting role="php"><![CDATA[
<!--
See http://developer.yahoo.com/ypatterns/pattern.php?pattern=searchpagination
-->

<?php if ($this->pageCount): ?>
<div class="paginationControl">
<!-- 前のページへのリンク -->
<?php if (isset($this->previous)): ?>
  <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
    &lt; Previous
  </a> |
<?php else: ?>
  <span class="disabled">&lt; Previous</span> |
<?php endif; ?>

<!-- ページ番号へのリンク -->
<?php foreach ($this->pagesInRange as $page): ?>
  <?php if ($page != $this->current): ?>
    <a href="<?php echo $this->url(array('page' => $page)); ?>">
        <?php echo $page; ?>
    </a> |
  <?php else: ?>
    <?php echo $page; ?> |
  <?php endif; ?>
<?php endforeach; ?>

<!-- 次のページへのリンク -->
<?php if (isset($this->next)): ?>
  <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
    Next &gt;
  </a>
<?php else: ?>
  <span class="disabled">Next &gt;</span>
<?php endif; ?>
</div>
<?php endif; ?>
]]>
                </programlisting>
            </para>

            <para>
                項目のページ処理

                <programlisting role="php"><![CDATA[
<!--
See http://developer.yahoo.com/ypatterns/pattern.php?pattern=itempagination
-->

<?php if ($this->pageCount): ?>
<div class="paginationControl">
<?php echo $this->firstItemNumber; ?> - <?php echo $this->lastItemNumber; ?>
of <?php echo $this->totalItemCount; ?>

<!-- 最初のページへのリンク -->
<?php if (isset($this->previous)): ?>
  <a href="<?php echo $this->url(array('page' => $this->first)); ?>">
    First
  </a> |
<?php else: ?>
  <span class="disabled">First</span> |
<?php endif; ?>

<!-- 前のページへのリンク -->
<?php if (isset($this->previous)): ?>
  <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
    &lt; Previous
  </a> |
<?php else: ?>
  <span class="disabled">&lt; Previous</span> |
<?php endif; ?>

<!-- 次のページへのリンク -->
<?php if (isset($this->next)): ?>
  <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
    Next &gt;
  </a> |
<?php else: ?>
  <span class="disabled">Next &gt;</span> |
<?php endif; ?>

<!-- 最後のページへのリンク -->
<?php if (isset($this->next)): ?>
  <a href="<?php echo $this->url(array('page' => $this->last)); ?>">
    Last
  </a>
<?php else: ?>
  <span class="disabled">Last</span>
<?php endif; ?>

</div>
<?php endif; ?>
]]>
                </programlisting>
            </para>

            <para>
                ドロップダウンのページ処理

                <programlisting role="php"><![CDATA[
<?php if ($this->pageCount): ?>
<select id="paginationControl" size="1">
<?php foreach ($this->pagesInRange as $page): ?>
  <?php $selected = ($page == $this->current) ? ' selected="selected"' : ''; ?>
  <option value="<?php
        echo $this->url(array('page' => $page));?>"<?php echo $selected ?>>
    <?php echo $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>
]]>
                </programlisting>
            </para>
        </sect3>

        <sect3 id="zend.paginator.usage.rendering.properties">
            <title>プロパティの一覧</title>

            <para>
                次のオプションが、ページ処理コントロールのビュー
                partial で使用可能です。
            </para>

            <table id="zend.paginator.usage.rendering.properties.table">
                <title>ビュー partial のプロパティ</title>

                <tgroup cols="3">
                    <thead>
                        <row>
                            <entry>プロパティ</entry>
                            <entry>型</entry>
                            <entry>説明</entry>
                        </row>
                    </thead>
                    <tbody>
                        <row>
                            <entry>first</entry>
                            <entry>integer</entry>
                            <entry>最初のページ番号 (つまり 1)</entry>
                        </row>
                        <row>
                            <entry>firstItemNumber</entry>
                            <entry>integer</entry>
                            <entry>
                                このページの最初の項目の番号
                            </entry>
                        </row>
                        <row>
                            <entry>firstPageInRange</entry>
                            <entry>integer</entry>
                            <entry>
                                スクロール形式で返された範囲内の最初のページ
                            </entry>
                        </row>
                        <row>
                            <entry>current</entry>
                            <entry>integer</entry>
                            <entry>現在のページ番号</entry>
                        </row>
                        <row>
                            <entry>currentItemCount</entry>
                            <entry>integer</entry>
                            <entry>このページの項目の数</entry>
                        </row>
                        <row>
                            <entry>itemCountPerPage</entry>
                            <entry>integer</entry>
                            <entry>各ページに表示できる項目の最大数</entry>
                        </row>
                        <row>
                            <entry>last</entry>
                            <entry>integer</entry>
                            <entry>最後のページ番号</entry>
                        </row>
                        <row>
                            <entry>lastItemNumber</entry>
                            <entry>integer</entry>
                            <entry>
                                このページの最後の項目の番号
                            </entry>
                        </row>
                        <row>
                            <entry>lastPageInRange</entry>
                            <entry>integer</entry>
                            <entry>
                                スクロール形式で返された範囲内の最後のページ
                            </entry>
                        </row>
                        <row>
                            <entry>next</entry>
                            <entry>integer</entry>
                            <entry>次のページ番号</entry>
                        </row>
                        <row>
                            <entry>pageCount</entry>
                            <entry>integer</entry>
                            <entry>ページ数</entry>
                        </row>
                        <row>
                            <entry>pagesInRange</entry>
                            <entry>array</entry>
                            <entry>
                                スクロール形式で返されたページの配列
                            </entry>
                        </row>
                        <row>
                            <entry>previous</entry>
                            <entry>integer</entry>
                            <entry>前のページ番号</entry>
                        </row>
                        <row>
                            <entry>totalItemCount</entry>
                            <entry>integer</entry>
                            <entry>項目の総数</entry>
                        </row>
                    </tbody>
                </tgroup>
            </table>
        </sect3>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
