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

    <sect2 id="zend.paginator.usage.paginating">
        <title>Seitendarstellung von Datensammlungen</title>

        <para>
            Um Elemente in Seiten darzustellen muß <classname>Zend_Paginator</classname> einen
            generellen Weg des Zugriffs auf diese Daten haben. Für diesen Zweck, läuft jeder
            Datenzugriff über Datenquellen Adapter. Verschiedene Adapter werden mit dem Zend
            Framework standardmäßig ausgeliefert:
        </para>

        <table id="zend.paginator.usage.paginating.adapters">
            <title>Adapter für Zend_Paginator</title>

            <tgroup cols="2">
                <thead>
                    <row>
                        <entry>Adapter</entry>
                        <entry>Beschreibung</entry>
                    </row>
                </thead>

                <tbody>
                    <row>
                        <entry>Array</entry>
                        <entry>Verwendet ein <acronym>PHP</acronym> Array</entry>
                    </row>

                    <row>
                        <entry>DbSelect</entry>

                        <entry>
                            Verwendet eine Instanz von <link
                                linkend="zend.db.select"><classname>Zend_Db_Select</classname></link>,
                            welche ein Array zurückgibt
                        </entry>
                    </row>

                    <row>
                        <entry>DbTableSelect</entry>

                        <entry>
                            Verwendet eine Instanz von <link
                                linkend="zend.db.table.fetch-all"><classname>Zend_Db_Table_Select</classname></link>,
                            welche eine Instanz von
                            <classname>Zend_Db_Table_Rowset_Abstract</classname> zurückgibt. Das
                            gibt zusätzliche Information pber das Ergebnisset, wie z.B. die Namen
                            der Spalten.
                        </entry>
                    </row>

                    <row>
                        <entry>Iterator</entry>

                        <entry>
                            Verwendet eine Instanz von <ulink
                                url="http://www.php.net/~helly/php/ext/spl/interfaceIterator.html"><classname>Iterator</classname></ulink>
                        </entry>
                    </row>

                    <row>
                        <entry>Null</entry>

                        <entry>
                            <classname>Zend_Paginator</classname> nicht für das Verwalten von
                            seitenweisen Daten verwenden. Man kann trotzdem die Vorteile des
                            Features der Seitenkontrolle verwenden.
                        </entry>
                    </row>
                </tbody>
            </tgroup>
        </table>

        <note>
            <para>
                Statt jede passende Zeile einer gegebenen Abfrage auszuwählen, empfangen die
                DbSelect und DbTableSelect Adapter nur die kleinste Anzahl an Daten die für die
                Darstellung der aktuellen Seite notwendig sind.
            </para>

            <para>
                Deswegen wird dynamisch eine zweite Abfrage erzeugt um die komplette Anzahl an
                passenden Zeilen festzustellen. Trotzdem ist es möglich die Anzahl oder die Abfrage
                für die Anzahl selbst direkt zu übergeben. Siehe die
                <methodname>setRowCount()</methodname> Methode im DbSelect Adapter für weitere
                Informationen.
            </para>
        </note>

        <para>
            Um eine Instanz von <classname>Zend_Paginator</classname> zu erstellen, muß ein Adapter
            an den Konstruktor übergeben werden:
        </para>

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

        <para>
            Der Einfachheit halber kann man für die mit dem Zend Framework mitgelieferten Adapter
            die statische <methodname>factory()</methodname> verwenden:
        </para>

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

        <note>
            <para>
                Im Falle des <constant>NULL</constant> Adapters, muß dem Konstruktor eine
                Elementanzahl mitgegeben werden da keine Datensammlung vorliegt.
            </para>
        </note>

        <para>
            Auch wenn die Instanz in diesem Fall technische zu verwenden ist, muß in der Controller
            Aktion der Seitendarstellung mitgeteilt werden welche Seitennummer der Benutzer
            angefragt hat. Das erlaubt Ihm auf die seitenweisen Daten zuzugreifen.
        </para>

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

        <para>
            Der einfachste Weg um diesen Wert zu verfolgen ist über eine <acronym>URL</acronym>.
            Auch wenn wir empfehlen einen
            <classname>Zend_Controller_Router_Interface</classname>-kompatiblen
            Router zu verwenden um dies zu bewerkstelligen, ist das keine Notwendigkeit.
        </para>

        <para>
            Das folgende ist eine Beispielroute die in einer <acronym>INI</acronym>
            Konfigurationsdatei verwendet werden könnte:
        </para>

        <programlisting language="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>
            Mit der obigen Route (und der Verwendung der Zend Framework <acronym>MVC</acronym>
            Komponenten), kann die aktuelle Seitenzahl wie folgt gesetzt werden:
        </para>

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

        <para>
            Es sind auch andere Optionen vorhanden; siehe
            <link linkend="zend.paginator.configuration">Konfiguration</link> für zusätzliche
            Informationen.
        </para>

        <para>
            Schlußendlich muß die Paginator Instanz der View angehängt werden. Wenn
            <classname>Zend_View</classname> mit dem ViewRenderer Action Helfer verwendet wird, dann
            funktioniert das folgende:
        </para>

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

    <sect2 id="zend.paginator.usage.dbselect">
        <title>Die Adapter DbSelect und DbTableSelect</title>

        <para>
            Die Verwendung der meisten Adapter ist recht zielgerichtet. Trotzdem benötigen die
            Datenbank Adapter detailiertere Erklärungen betreffend dem Empfang und dem Zählen von
            Daten aus der Datenbank.
        </para>

        <para>
            Um die DbSelect und DbTableSelect Adapter zu verwenden muß man die Daten nicht direkt
            von der Datenbank empfangen. Beide Adapter führen den Empfang selbst durch, und Zählen
            auch die Anzahl der Seiten. Wenn zusätzliche Arbeit basieren auf den Ergebnissen des
            Adapters getan werden soll, kann die <methodname>getItems()</methodname> Methode des
            Adapters in der eigenen Anwendung erweitert werden.
        </para>

        <para>
            Zusätzlich holen diese Adapter <emphasis>nicht</emphasis> alle Einträge von der
            Datenbank um sie zu zählen. Stattdessen manipuliert der Adapter die originale Abfrage um
            die entsprechende COUNT Abfrage zu erzeugen. Paginator führt dann diese COUNT Abfrage
            aus um die Anzahl der Zeilen zu erhalten. Das erfordert eine zusätzliche Beanspruchung
            der Datenbank, ist aber um ein vielfaches schneller als das komplette Ergebnisset zu
            holen und <methodname>count()</methodname> zu verwenden. Speziell bei einer großen
            Anzahl an Daten.
        </para>

        <para>
            Der Datenbank Adapter versucht die effizienteste Abfrage zu erstellen die auf ziemlich
            allen modernen Datenbanken ausgefürt wird. Trotzdem ist es möglich das, abhängig von
            der eigenen Datenbank oder sogar dem Setup des eigenen Schemas, ein effizienterer Weg
            existiert um die Anzahl der Zeilen zu erhalten. Für dieses Szenario erlaubt es der
            Datenbank Adapter eine eigene COUNT Abfrage zu setzen. Wenn man zum Beispiel die
            Anzahl der Blog Posts in einer eigenen Tabelle speichert, kann eine schnellere Abfrage
            der Anzahl mit dem folgenden Setup erreicht werden:
        </para>

        <programlisting language="php"><![CDATA[
$adapter = new Zend_Paginator_Adapter_DbSelect($db->select()->from('posts'));
$adapter->setRowCount(
    $db->select()
       ->from(
           'item_counts',
           array(
               Zend_Paginator_Adapter_DbSelect::ROW_COUNT_COLUMN => 'post_count'
           )
       )
);

$paginator = new Zend_Paginator($adapter);
]]></programlisting>

        <para>
            Dieser Ansatz wird jetzt wahrscheinlich keine große Performance Verbesserung bei
            kleinen Datemengen und oder einfachen Abfragen ergeben. Aber bei komplexen Abfragen
            und großen Datenmengen kann ein ähnlicher Weg eine signifikante Performance
            Verbesserung ergeben.
        </para>
    </sect2>

    <sect2 id="zend.paginator.rendering">
        <title>Seiten mit View Skripten darstellen</title>

        <para>
            Das View Skript wird verwendet um die Seitenelemente darzustellen (wenn
            <classname>Zend_Paginator</classname> verwendet wird um das zu tun) und die
            Seitenkontrollen anzuzeigen.
        </para>

        <para>
            Weil <classname>Zend_Paginator</classname> Das <acronym>SPL</acronym> Interface <ulink
                url="http://www.php.net/~helly/php/ext/spl/interfaceIteratorAggregate.html"><classname>IteratorAggregate</classname></ulink>
            integriert, ist das Durchlaufen von Elementen und deren Darstellung einfach.
        </para>

        <programlisting language="php"><![CDATA[
<html>
<body>
<h1>Beispiel</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>
            Der Aufruf des View Helfers fast am Ende ist zu beachten. PaginationControl nimmt bis zu
            vier Parameter: die Paginator Instanz, einen Scrolling Stil, eine partielle View und ein
            Array von zusätzlichen Parametern.
        </para>

        <para>
            Die zweiten und dritten Parameter sind sehr wichtig. Wobei die partielle View verwendet
            wird um festzustellen wie die Seitenkontrollen <emphasis>aussehen</emphasis> sollten,
            und der Scrolling Stil verwendet wird um zu kontrollieren wie er sich
            <emphasis>verhalten</emphasis> sollte. Angenommen die partielle View ist im Stil einer
            Suchseiten Kontrolle, wie anbei:
        </para>

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

        <para>
            Was passiert wenn der Benutzer den "next" Link ein paar Mal anklickt? Nun, viele Dinge
            könnten geschehen. Die aktuelle Seitennummer könnte in der Mitte stehen während man
            durchklickt (wie sie es auf Yahoo macht!), oder sie könnte bis zum Ende des
            Seitenbereichs ansteigen und dann auf der linken Seite erscheinen wenn der Benutzer ein
            weiteres Mal "next" klickt. Die Seitennummer könnte sogar größer und kleiner werden
            während der Benutzer auf sie zugreift (oder "scrollt). (wie es auf Google geschieht).
        </para>

        <para>
            Es gibt view Scrolling Stile die mit dem Zend Framework geliefert werden:
        </para>

        <table id="zend.paginator.usage.rendering.scrolling-styles">
            <title>Scrolling Stile für Zend_Paginator</title>

            <tgroup cols="2">
                <thead>
                    <row>
                        <entry>Scrolling Stil</entry>
                        <entry>Beschreibung</entry>
                    </row>
                </thead>

                <tbody>
                    <row>
                        <entry>All</entry>

                        <entry>
                            Gibt alle Seiten zurück. Das ist für Seitenkontrollen mit Dropdownmenüs
                            nützlich wenn Sie relativ wenig Seiten haben. In diesen Fällen ist es
                            oft gewünscht alle vorhandenen Seiten dem Benutzer auf einmal
                            anzuzeigen.
                        </entry>
                    </row>

                    <row>
                        <entry>Elastic</entry>

                        <entry>
                            Eine Google-artiger Scrolling Stil der sich erweitert und verkleinert
                            wenn ein Benutzer durch die Seiten scrollt.
                        </entry>
                    </row>

                    <row>
                        <entry>Jumping</entry>

                        <entry>
                            Wenn Benutzer scrollen, steigt die Seitenzahl bis zum Ende eines
                            gegebenen Bereichs, und startet anschließend wieder beim Beginn eines
                            neuen Bereichs.
                        </entry>
                    </row>

                    <row>
                        <entry>Sliding</entry>

                        <entry>
                            Ein Yahoo!-artiger Scrolling Stil der die aktuelle Seitenzahl in der
                            Mitte des Seitenbereichs platziert, oder so nahe wie möglich. Das ist
                            der Standardstil.
                        </entry>
                    </row>
                </tbody>
            </tgroup>
        </table>

        <para>
            Der vierte und letzte Parameter ist reserviert für ein assoziatives Array an
            zusätzlichen Variablen das in der partiellen View vorhanden sein sill (über
            <varname>$this</varname>). Für Instanzen, können diese Werte extra
            <acronym>URL</acronym> Parameter für Seitendarstellungslinks enthalten.
        </para>

        <para>
            Durch das Setzen von einer standardmäßigen partiellen View, einem standardmäßigen
            Scrolling Stil und einer View Instanz kann dei Aufruf der PaginationControl komplett
            eliminiert werden:
        </para>

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

        <para>
            Wenn alle diese Werte gesetzt sind, kann die Seitenkontrolle im View Skript mit einem
            einfachen echo Statement dargestellt werden:
        </para>

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

        <note>
            <para>
                Natürlich ist es möglich <classname>Zend_Paginator</classname> mit anderen Template
                Engines zu verwenden. Mit Smarty zum Beispiel, würde man das folgendermaßen
                bewerkstelligen:
            </para>

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

            <para>
                Man könnte die Seitenverte von einem Template wie folgt erhalten:
            </para>

            <programlisting language="php"><![CDATA[
{$pages->pageCount}
]]></programlisting>
        </note>

        <sect3 id="zend.paginator.usage.rendering.example-controls">
            <title>Beispiel der Seitenkontrolle</title>

            <para>
                Das folgende Beispiel von Seitenkontrollen wird Ihnen hoffentlich helfen um erstmals
                anzufangen:
            </para>

            <para>
                Such-Seitendarstellung
            </para>

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

<?php if ($this->pageCount): ?>
<div class="paginationControl">
<!-- Vorheriger Seitenlink -->
<?php if (isset($this->previous)): ?>
  <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
    &lt; Vorher
  </a> |
<?php else: ?>
  <span class="disabled">&lt; Vorher</span> |
<?php endif; ?>

<!-- Anzahl an Seitenlinks -->
<?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; ?>

<!-- Nächster Seitenlink -->
<?php if (isset($this->next)): ?>
  <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
    Nächster &gt;
  </a>
<?php else: ?>
  <span class="disabled">Nächster &gt;</span>
<?php endif; ?>
</div>
<?php endif; ?>
]]></programlisting>

            <para>
                Element Seitendarstellung:
            </para>

            <programlisting language="php"><![CDATA[
<!--
Siehe 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; ?>

<!-- First page link -->
<?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; ?>

<!-- Vorheriger Seitenlink -->
<?php if (isset($this->previous)): ?>
  <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
    &lt; Vorheriger
  </a> |
<?php else: ?>
  <span class="disabled">&lt; Vorheriger</span> |
<?php endif; ?>

<!-- Next page link -->
<?php if (isset($this->next)): ?>
  <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
    Nächster &gt;
  </a> |
<?php else: ?>
  <span class="disabled">Nächster &gt;</span> |
<?php endif; ?>

<!-- Last page link -->
<?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>
                Dropdown Seitendarstellung:
            </para>

            <programlisting language="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>
        </sect3>

        <sect3 id="zend.paginator.usage.rendering.properties">
            <title>Tabelle von Eigenschaften</title>

            <para>
                Die folgenden Optionen von für eine Seitenkontrolle bei View Partials vorhanden:
            </para>

            <table id="zend.paginator.usage.rendering.properties.table">
                <title>Eigenschaften die bei View Partials vorhanden sind</title>

                <tgroup cols="3">
                    <thead>
                        <row>
                            <entry>Eigenschaft</entry>
                            <entry>Typ</entry>
                            <entry>Beschreibung</entry>
                        </row>
                    </thead>

                    <tbody>
                        <row>
                            <entry>first</entry>
                            <entry>integer</entry>
                            <entry>Erste Seitennummer (z.B., 1)</entry>
                        </row>

                        <row>
                            <entry>firstItemNumber</entry>
                            <entry>integer</entry>
                            <entry>Absolute Nummer des ersten Elements auf dieser Seite</entry>
                        </row>

                        <row>
                            <entry>firstPageInRange</entry>
                            <entry>integer</entry>

                            <entry>
                                Erste Seite des Bereichs der vom Scrolling Stil zurückgegeben wird
                            </entry>
                        </row>

                        <row>
                            <entry>current</entry>
                            <entry>integer</entry>
                            <entry>Aktuelle Seitenzahl</entry>
                        </row>

                        <row>
                            <entry>currentItemCount</entry>
                            <entry>integer</entry>
                            <entry>Anzahl der Elemente auf dieser Seite</entry>
                        </row>

                        <row>
                            <entry>itemCountPerPage</entry>
                            <entry>integer</entry>

                            <entry>
                                Maximale Anzahl der Elemente die auf jeder Seite vorhanden sind
                            </entry>
                        </row>

                        <row>
                            <entry>last</entry>
                            <entry>integer</entry>
                            <entry>Letzte Seitennummer</entry>
                        </row>

                        <row>
                            <entry>lastItemNumber</entry>
                            <entry>integer</entry>
                            <entry>Absolute Zahl des letzten Elements auf dieser Seite</entry>
                        </row>

                        <row>
                            <entry>lastPageInRange</entry>
                            <entry>integer</entry>

                            <entry>
                                Letzte Seite im Bereich der vom Scrolling Stil zurückgegeben wird
                            </entry>
                        </row>

                        <row>
                            <entry>next</entry>
                            <entry>integer</entry>
                            <entry>Nächste Seitenzahl</entry>
                        </row>

                        <row>
                            <entry>pageCount</entry>
                            <entry>integer</entry>
                            <entry>Anzahl an Seiten</entry>
                        </row>

                        <row>
                            <entry>pagesInRange</entry>
                            <entry>array</entry>

                            <entry>
                                Array von Seiten das vom Scrolling Stil zurückgegeben wird
                            </entry>
                        </row>

                        <row>
                            <entry>previous</entry>
                            <entry>integer</entry>
                            <entry>Vorherige Seitenzahl</entry>
                        </row>

                        <row>
                            <entry>totalItemCount</entry>
                            <entry>integer</entry>
                            <entry>Komplette Anzahl an Elementen</entry>
                        </row>
                    </tbody>
                </tgroup>
            </table>
        </sect3>
    </sect2>
</sect1>
