[MANUAL] English:
[zend.git] / documentation / manual / en / module_specs / Zend_Paginator-Usage.xml
blobdf7b35446338fedaacdd3bd5491620ac93cf8e02
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.paginator.usage">
4     <title>Usage</title>
6     <sect2 id="zend.paginator.usage.paginating">
7         <title>Paginating data collections</title>
9         <para>
10             In order to paginate items into pages, <classname>Zend_Paginator</classname>
11             must have a generic way of accessing that data. For that reason,
12             all data access takes place through data source adapters. Several
13             adapters ship with Zend Framework by default:
14         </para>
16         <table id="zend.paginator.usage.paginating.adapters">
17             <title>Adapters for Zend_Paginator</title>
19             <tgroup cols="2">
20                 <thead>
21                     <row>
22                         <entry>Adapter</entry>
23                         <entry>Description</entry>
24                     </row>
25                 </thead>
27                 <tbody>
28                     <row>
29                         <entry>Array</entry>
30                         <entry>Use a <acronym>PHP</acronym> array</entry>
31                     </row>
33                     <row>
34                         <entry>DbSelect</entry>
36                         <entry>
37                             Use a <link
38                                 linkend="zend.db.select"><classname>Zend_Db_Select</classname></link>
39                             instance, which will return an array
40                         </entry>
41                     </row>
43                     <row>
44                         <entry>DbTableSelect</entry>
46                         <entry>
47                             Use a <link
48                                 linkend="zend.db.table.fetch-all"><classname>Zend_Db_Table_Select</classname></link>
49                             instance, which will return an instance of
50                             <classname>Zend_Db_Table_Rowset_Abstract</classname>.
51                             This provides additional information about the
52                             result set, such as column names.
53                         </entry>
54                     </row>
56                     <row>
57                         <entry>Iterator</entry>
59                         <entry>
60                             Use an <ulink
61                                 url="http://www.php.net/~helly/php/ext/spl/interfaceIterator.html"><classname>Iterator</classname></ulink>
62                             instance
63                         </entry>
64                     </row>
66                     <row>
67                         <entry>Null</entry>
69                         <entry>
70                             Do not use <classname>Zend_Paginator</classname> to manage
71                             data pagination. You can still take advantage of
72                             the pagination control feature.
73                         </entry>
74                     </row>
75                 </tbody>
76             </tgroup>
77         </table>
79         <note>
80             <para>
81                 Instead of selecting every matching row of a given query, the
82                 DbSelect and DbTableSelect adapters retrieve only the smallest
83                 amount of data necessary for displaying the current page.
84             </para>
86             <para>
87                 Because of this, a second query is dynamically generated to
88                 determine the total number of matching rows. However, it is
89                 possible to directly supply a count or count query yourself.
90                 See the <methodname>setRowCount()</methodname> method in the DbSelect
91                 adapter for more information.
92             </para>
93         </note>
95         <para>
96             To create an instance of <classname>Zend_Paginator</classname>, you must
97             supply an adapter to the constructor:
98         </para>
100         <programlisting language="php"><![CDATA[
101 $paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($array));
102 ]]></programlisting>
104         <para>
105             For convenience, you may take advantage of the static
106             <methodname>factory()</methodname> method for the adapters packaged with Zend
107             Framework:
108         </para>
110         <programlisting language="php"><![CDATA[
111 $paginator = Zend_Paginator::factory($array);
112 ]]></programlisting>
114         <note>
115             <para>
116                 In the case of the <classname>Null</classname> adapter, in lieu of a data collection
117                 you must supply an item count to its constructor.
118             </para>
119         </note>
121         <para>
122             Although the instance is technically usable in this state, in your
123             controller action you'll need to tell the paginator what page
124             number the user requested. This allows him to advance through the
125             paginated data.
126         </para>
128         <programlisting language="php"><![CDATA[
129 $paginator->setCurrentPageNumber($page);
130 ]]></programlisting>
132         <para>
133             The simplest way to keep track of this value is through a <acronym>URL</acronym>.
134             Although we recommend using a
135             <classname>Zend_Controller_Router_Interface</classname>-compatible
136             router to handle this, it is not a requirement.
137         </para>
139         <para>
140             The following is an example route you might use in an <acronym>INI</acronym>
141             configuration file:
142         </para>
144         <programlisting language="php"><![CDATA[
145 routes.example.route = articles/:articleName/:page
146 routes.example.defaults.controller = articles
147 routes.example.defaults.action = view
148 routes.example.defaults.page = 1
149 routes.example.reqs.articleName = \w+
150 routes.example.reqs.page = \d+
151 ]]></programlisting>
153         <para>
154             With the above route (and using Zend Framework <acronym>MVC</acronym> components),
155             you might set the current page number like this:
156         </para>
158         <programlisting language="php"><![CDATA[
159 $paginator->setCurrentPageNumber($this->_getParam('page'));
160 ]]></programlisting>
162         <para>
163             There are other options available; see
164             <link linkend="zend.paginator.configuration">Configuration</link>
165             for more on them.
166         </para>
168         <para>
169             Finally, you'll need to assign the paginator instance to your view.
170             If you're using <classname>Zend_View</classname> with the ViewRenderer action
171             helper, the following will work:
172         </para>
174         <programlisting language="php"><![CDATA[
175 $this->view->paginator = $paginator;
176 ]]></programlisting>
177     </sect2>
179     <sect2 id="zend.paginator.usage.dbselect">
180         <title>The DbSelect and DbTableSelect adapter</title>
182         <para>
183             The usage of most adapters is pretty straight-forward. However, the
184             database adapters require a more detailed explanation regarding
185             the retrieval and count of the data from the database.
186         </para>
188         <para>
189             To use the DbSelect and DbTableSelect adapters you don't have to retrieve the data
190             upfront from the database. Both adapters do the retrieval for you, aswell as the
191             counting of the total pages. If additional work has to be done on the database results
192             the adapter <methodname>getItems()</methodname> method has to be extended in your
193             application.
194         </para>
196         <para>
197             Additionally these adapters do <emphasis>not</emphasis> fetch all records from the
198             database in order to count them. Instead, the adapters manipulates the original query to
199             produce the corresponding COUNT query. Paginator then executes that COUNT query to get
200             the number of rows. This does require an extra round-trip to the database, but this is
201             many times faster than fetching an entire result set and using
202             <methodname>count()</methodname>. Especially with large collections of data.
203         </para>
205         <para>
206             The database adapters will try and build the most efficient query that will execute
207             on pretty much all modern databases. However, depending on your database or even your
208             own schema setup, there might be more efficient ways to get a rowcount. For this
209             scenario the database adapters allow you to set a custom COUNT query. For example,
210             if you keep track of the count of blog posts in a separate table, you could achieve a
211             faster count query with the following setup:
212         </para>
214         <programlisting language="php"><![CDATA[
215 $adapter = new Zend_Paginator_Adapter_DbSelect($db->select()->from('posts'));
216 $adapter->setRowCount(
217     $db->select()
218        ->from(
219             'item_counts',
220             array(
221                Zend_Paginator_Adapter_DbSelect::ROW_COUNT_COLUMN => 'post_count'
222             )
223          )
226 $paginator = new Zend_Paginator($adapter);
227 ]]></programlisting>
229         <para>
230             This approach will probably not give you a huge performance gain on
231             small collections and/or simple select queries. However, with complex
232             queries and large collections, a similar approach could give you a
233             significant performance boost.
234         </para>
235     </sect2>
237     <sect2 id="zend.paginator.rendering">
238         <title>Rendering pages with view scripts</title>
240         <para>
241             The view script is used to render the page items (if you're using
242             <classname>Zend_Paginator</classname> to do so) and display the pagination
243             control.
244         </para>
246         <para>
247             Because <classname>Zend_Paginator</classname> implements the <acronym>SPL</acronym>
248             interface <ulink
249                 url="http://www.php.net/~helly/php/ext/spl/interfaceIteratorAggregate.html"><classname>IteratorAggregate</classname></ulink>,
250             looping over your items and displaying them is simple.
251         </para>
253         <programlisting language="php"><![CDATA[
254 <html>
255 <body>
256 <h1>Example</h1>
257 <?php if (count($this->paginator)): ?>
258 <ul>
259 <?php foreach ($this->paginator as $item): ?>
260   <li><?php echo $item; ?></li>
261 <?php endforeach; ?>
262 </ul>
263 <?php endif; ?>
265 <?php echo $this->paginationControl($this->paginator,
266                                     'Sliding',
267                                     'my_pagination_control.phtml'); ?>
268 </body>
269 </html>
270 ]]></programlisting>
272         <para>
273             Notice the view helper call near the end. PaginationControl
274             accepts up to four parameters: the paginator instance, a scrolling
275             style, a view partial, and an array of additional parameters.
276         </para>
278         <para>
279             The second and third parameters are very important. Whereas the
280             view partial is used to determine how the pagination control should
281             <emphasis>look</emphasis>, the scrolling style is used to control
282             how it should <emphasis>behave</emphasis>. Say the view partial is
283             in the style of a search pagination control, like the one below:
284         </para>
286         <para>
287             <inlinegraphic align="center" valign="middle"
288                 fileref="figures/zend.paginator.usage.rendering.control.png"
289                 format="PNG"/>
290         </para>
292         <para>
293             What happens when the user clicks the "next" link a few times?
294             Well, any number of things could happen. The current page number
295             could stay in the middle as you click through (as it does on
296             Yahoo!), or it could advance to the end of the page range and then
297             appear again on the left when the user clicks "next" one more time.
298             The page numbers might even expand and contract as the user
299             advances (or "scrolls") through them (as they do on Google).
300         </para>
302         <para>
303             There are four scrolling styles packaged with Zend Framework:
304         </para>
306         <table id="zend.paginator.usage.rendering.scrolling-styles">
307             <title>Scrolling styles for Zend_Paginator</title>
309             <tgroup cols="2">
310                 <thead>
311                     <row>
312                         <entry>Scrolling style</entry>
313                         <entry>Description</entry>
314                     </row>
315                 </thead>
317                 <tbody>
318                     <row>
319                         <entry>All</entry>
321                         <entry>
322                             Returns every page. This is useful for dropdown
323                             menu pagination controls with relatively few
324                             pages. In these cases, you want all pages
325                             available to the user at once.
326                         </entry>
327                     </row>
329                     <row>
330                         <entry>Elastic</entry>
332                         <entry>
333                             A Google-like scrolling style that expands and
334                             contracts as a user scrolls through the pages.
335                         </entry>
336                     </row>
338                     <row>
339                         <entry>Jumping</entry>
341                         <entry>
342                             As users scroll through, the page number advances
343                             to the end of a given range, then starts again at
344                             the beginning of the new range.
345                         </entry>
346                     </row>
348                     <row>
349                         <entry>Sliding</entry>
351                         <entry>
352                             A Yahoo!-like scrolling style that positions the
353                             current page number in the center of the page
354                             range, or as close as possible. This is the
355                             default style.
356                         </entry>
357                     </row>
358                 </tbody>
359             </tgroup>
360         </table>
362         <para>
363             The fourth and final parameter is reserved for an optional
364             associative array of additional variables that you want available
365             in your view partial (available via <varname>$this</varname>). For
366             instance, these values could include extra <acronym>URL</acronym> parameters for
367             pagination links.
368         </para>
370         <para>
371             By setting the default view partial, default
372             scrolling style, and view instance, you can eliminate the calls to
373             PaginationControl completely:
374         </para>
376         <programlisting language="php"><![CDATA[
377 Zend_Paginator::setDefaultScrollingStyle('Sliding');
378 Zend_View_Helper_PaginationControl::setDefaultViewPartial(
379     'my_pagination_control.phtml'
381 $paginator->setView($view);
382 ]]></programlisting>
384         <para>
385             When all of these values are set, you can render the pagination
386             control inside your view script with a simple echo statement:
387         </para>
389         <programlisting language="php"><![CDATA[
390 <?php echo $this->paginator; ?>
391 ]]></programlisting>
393         <note>
394             <para>
395                 Of course, it's possible to use <classname>Zend_Paginator</classname>
396                 with other template engines. For example, with Smarty you
397                 might do the following:
398             </para>
400             <programlisting language="php"><![CDATA[
401 $smarty->assign('pages', $paginator->getPages());
402 ]]></programlisting>
404             <para>
405                 You could then access paginator values from a template like so:
406             </para>
408             <programlisting language="php"><![CDATA[
409 {$pages->pageCount}
410 ]]></programlisting>
411         </note>
413         <sect3 id="zend.paginator.usage.rendering.example-controls">
414             <title>Example pagination controls</title>
416             <para>
417                 The following example pagination controls will hopefully help
418                 you get started:
419             </para>
421             <para>
422                 Search pagination:
423             </para>
425             <programlisting language="php"><![CDATA[
426 <!--
427 See http://developer.yahoo.com/ypatterns/pattern.php?pattern=searchpagination
430 <?php if ($this->pageCount): ?>
431 <div class="paginationControl">
432 <!-- Previous page link -->
433 <?php if (isset($this->previous)): ?>
434   <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
435     &lt; Previous
436   </a> |
437 <?php else: ?>
438   <span class="disabled">&lt; Previous</span> |
439 <?php endif; ?>
441 <!-- Numbered page links -->
442 <?php foreach ($this->pagesInRange as $page): ?>
443   <?php if ($page != $this->current): ?>
444     <a href="<?php echo $this->url(array('page' => $page)); ?>">
445         <?php echo $page; ?>
446     </a> |
447   <?php else: ?>
448     <?php echo $page; ?> |
449   <?php endif; ?>
450 <?php endforeach; ?>
452 <!-- Next page link -->
453 <?php if (isset($this->next)): ?>
454   <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
455     Next &gt;
456   </a>
457 <?php else: ?>
458   <span class="disabled">Next &gt;</span>
459 <?php endif; ?>
460 </div>
461 <?php endif; ?>
462 ]]></programlisting>
464             <para>
465                 Item pagination:
466             </para>
468             <programlisting language="php"><![CDATA[
469 <!--
470 See http://developer.yahoo.com/ypatterns/pattern.php?pattern=itempagination
473 <?php if ($this->pageCount): ?>
474 <div class="paginationControl">
475 <?php echo $this->firstItemNumber; ?> - <?php echo $this->lastItemNumber; ?>
476 of <?php echo $this->totalItemCount; ?>
478 <!-- First page link -->
479 <?php if (isset($this->previous)): ?>
480   <a href="<?php echo $this->url(array('page' => $this->first)); ?>">
481     First
482   </a> |
483 <?php else: ?>
484   <span class="disabled">First</span> |
485 <?php endif; ?>
487 <!-- Previous page link -->
488 <?php if (isset($this->previous)): ?>
489   <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
490     &lt; Previous
491   </a> |
492 <?php else: ?>
493   <span class="disabled">&lt; Previous</span> |
494 <?php endif; ?>
496 <!-- Next page link -->
497 <?php if (isset($this->next)): ?>
498   <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
499     Next &gt;
500   </a> |
501 <?php else: ?>
502   <span class="disabled">Next &gt;</span> |
503 <?php endif; ?>
505 <!-- Last page link -->
506 <?php if (isset($this->next)): ?>
507   <a href="<?php echo $this->url(array('page' => $this->last)); ?>">
508     Last
509   </a>
510 <?php else: ?>
511   <span class="disabled">Last</span>
512 <?php endif; ?>
514 </div>
515 <?php endif; ?>
516 ]]></programlisting>
518             <para>
519                 Dropdown pagination:
520             </para>
522             <programlisting language="php"><![CDATA[
523 <?php if ($this->pageCount): ?>
524 <select id="paginationControl" size="1">
525 <?php foreach ($this->pagesInRange as $page): ?>
526   <?php $selected = ($page == $this->current) ? ' selected="selected"' : ''; ?>
527   <option value="<?php
528         echo $this->url(array('page' => $page));?>"<?php echo $selected ?>>
529     <?php echo $page; ?>
530   </option>
531 <?php endforeach; ?>
532 </select>
533 <?php endif; ?>
535 <script type="text/javascript"
536      src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js">
537 </script>
538 <script type="text/javascript">
539 $('paginationControl').observe('change', function() {
540     window.location = this.options[this.selectedIndex].value;
542 </script>
543 ]]></programlisting>
544         </sect3>
546         <sect3 id="zend.paginator.usage.rendering.properties">
547             <title>Listing of properties</title>
549             <para>
550                 The following options are available to pagination control
551                 view partials:
552             </para>
554             <table id="zend.paginator.usage.rendering.properties.table">
555                 <title>Properties available to view partials</title>
557                 <tgroup cols="3">
558                     <thead>
559                         <row>
560                             <entry>Property</entry>
561                             <entry>Type</entry>
562                             <entry>Description</entry>
563                         </row>
564                     </thead>
566                     <tbody>
567                         <row>
568                             <entry>first</entry>
569                             <entry>integer</entry>
570                             <entry>First page number (i.e., 1)</entry>
571                         </row>
573                         <row>
574                             <entry>firstItemNumber</entry>
575                             <entry>integer</entry>
576                             <entry>Absolute number of the first item on this page</entry>
577                         </row>
579                         <row>
580                             <entry>firstPageInRange</entry>
581                             <entry>integer</entry>
582                             <entry>First page in the range returned by the scrolling style</entry>
583                         </row>
585                         <row>
586                             <entry>current</entry>
587                             <entry>integer</entry>
588                             <entry>Current page number</entry>
589                         </row>
591                         <row>
592                             <entry>currentItemCount</entry>
593                             <entry>integer</entry>
594                             <entry>Number of items on this page</entry>
595                         </row>
597                         <row>
598                             <entry>itemCountPerPage</entry>
599                             <entry>integer</entry>
600                             <entry>Maximum number of items available to each page</entry>
601                         </row>
603                         <row>
604                             <entry>last</entry>
605                             <entry>integer</entry>
606                             <entry>Last page number</entry>
607                         </row>
609                         <row>
610                             <entry>lastItemNumber</entry>
611                             <entry>integer</entry>
612                             <entry>Absolute number of the last item on this page</entry>
613                         </row>
615                         <row>
616                             <entry>lastPageInRange</entry>
617                             <entry>integer</entry>
618                             <entry>Last page in the range returned by the scrolling style</entry>
619                         </row>
621                         <row>
622                             <entry>next</entry>
623                             <entry>integer</entry>
624                             <entry>Next page number</entry>
625                         </row>
627                         <row>
628                             <entry>pageCount</entry>
629                             <entry>integer</entry>
630                             <entry>Number of pages</entry>
631                         </row>
633                         <row>
634                             <entry>pagesInRange</entry>
635                             <entry>array</entry>
636                             <entry>Array of pages returned by the scrolling style</entry>
637                         </row>
639                         <row>
640                             <entry>previous</entry>
641                             <entry>integer</entry>
642                             <entry>Previous page number</entry>
643                         </row>
645                         <row>
646                             <entry>totalItemCount</entry>
647                             <entry>integer</entry>
648                             <entry>Total number of items</entry>
649                         </row>
650                     </tbody>
651                 </tgroup>
652             </table>
653         </sect3>
654     </sect2>
655 </sect1>
656 <!--
657 vim:se ts=4 sw=4 et: