1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect1 id="zend.paginator.usage">
6 <sect2 id="zend.paginator.usage.paginating">
7 <title>Paginating data collections</title>
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:
16 <table id="zend.paginator.usage.paginating.adapters">
17 <title>Adapters for Zend_Paginator</title>
22 <entry>Adapter</entry>
23 <entry>Description</entry>
30 <entry>Use a <acronym>PHP</acronym> array</entry>
34 <entry>DbSelect</entry>
38 linkend="zend.db.select"><classname>Zend_Db_Select</classname></link>
39 instance, which will return an array
44 <entry>DbTableSelect</entry>
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.
57 <entry>Iterator</entry>
61 url="http://www.php.net/~helly/php/ext/spl/interfaceIterator.html"><classname>Iterator</classname></ulink>
70 Do not use <classname>Zend_Paginator</classname> to manage
71 data pagination. You can still take advantage of
72 the pagination control feature.
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.
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.
96 To create an instance of <classname>Zend_Paginator</classname>, you must
97 supply an adapter to the constructor:
100 <programlisting language="php"><![CDATA[
101 $paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($array));
105 For convenience, you may take advantage of the static
106 <methodname>factory()</methodname> method for the adapters packaged with Zend
110 <programlisting language="php"><![CDATA[
111 $paginator = Zend_Paginator::factory($array);
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.
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
128 <programlisting language="php"><![CDATA[
129 $paginator->setCurrentPageNumber($page);
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.
140 The following is an example route you might use in an <acronym>INI</acronym>
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+
154 With the above route (and using Zend Framework <acronym>MVC</acronym> components),
155 you might set the current page number like this:
158 <programlisting language="php"><![CDATA[
159 $paginator->setCurrentPageNumber($this->_getParam('page'));
163 There are other options available; see
164 <link linkend="zend.paginator.configuration">Configuration</link>
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:
174 <programlisting language="php"><![CDATA[
175 $this->view->paginator = $paginator;
179 <sect2 id="zend.paginator.usage.dbselect">
180 <title>The DbSelect and DbTableSelect adapter</title>
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.
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
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.
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:
214 <programlisting language="php"><![CDATA[
215 $adapter = new Zend_Paginator_Adapter_DbSelect($db->select()->from('posts'));
216 $adapter->setRowCount(
221 Zend_Paginator_Adapter_DbSelect::ROW_COUNT_COLUMN => 'post_count'
226 $paginator = new Zend_Paginator($adapter);
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.
237 <sect2 id="zend.paginator.rendering">
238 <title>Rendering pages with view scripts</title>
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
247 Because <classname>Zend_Paginator</classname> implements the <acronym>SPL</acronym>
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.
253 <programlisting language="php"><![CDATA[
257 <?php if (count($this->paginator)): ?>
259 <?php foreach ($this->paginator as $item): ?>
260 <li><?php echo $item; ?></li>
265 <?php echo $this->paginationControl($this->paginator,
267 'my_pagination_control.phtml'); ?>
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.
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:
287 <inlinegraphic align="center" valign="middle"
288 fileref="figures/zend.paginator.usage.rendering.control.png"
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).
303 There are four scrolling styles packaged with Zend Framework:
306 <table id="zend.paginator.usage.rendering.scrolling-styles">
307 <title>Scrolling styles for Zend_Paginator</title>
312 <entry>Scrolling style</entry>
313 <entry>Description</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.
330 <entry>Elastic</entry>
333 A Google-like scrolling style that expands and
334 contracts as a user scrolls through the pages.
339 <entry>Jumping</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.
349 <entry>Sliding</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
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
371 By setting the default view partial, default
372 scrolling style, and view instance, you can eliminate the calls to
373 PaginationControl completely:
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);
385 When all of these values are set, you can render the pagination
386 control inside your view script with a simple echo statement:
389 <programlisting language="php"><![CDATA[
390 <?php echo $this->paginator; ?>
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:
400 <programlisting language="php"><![CDATA[
401 $smarty->assign('pages', $paginator->getPages());
405 You could then access paginator values from a template like so:
408 <programlisting language="php"><![CDATA[
413 <sect3 id="zend.paginator.usage.rendering.example-controls">
414 <title>Example pagination controls</title>
417 The following example pagination controls will hopefully help
425 <programlisting language="php"><![CDATA[
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)); ?>">
438 <span class="disabled">< Previous</span> |
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)); ?>">
448 <?php echo $page; ?> |
452 <!-- Next page link -->
453 <?php if (isset($this->next)): ?>
454 <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
458 <span class="disabled">Next ></span>
468 <programlisting language="php"><![CDATA[
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)); ?>">
484 <span class="disabled">First</span> |
487 <!-- Previous page link -->
488 <?php if (isset($this->previous)): ?>
489 <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
493 <span class="disabled">< Previous</span> |
496 <!-- Next page link -->
497 <?php if (isset($this->next)): ?>
498 <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
502 <span class="disabled">Next ></span> |
505 <!-- Last page link -->
506 <?php if (isset($this->next)): ?>
507 <a href="<?php echo $this->url(array('page' => $this->last)); ?>">
511 <span class="disabled">Last</span>
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"' : ''; ?>
528 echo $this->url(array('page' => $page));?>"<?php echo $selected ?>>
535 <script type="text/javascript"
536 src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js">
538 <script type="text/javascript">
539 $('paginationControl').observe('change', function() {
540 window.location = this.options[this.selectedIndex].value;
546 <sect3 id="zend.paginator.usage.rendering.properties">
547 <title>Listing of properties</title>
550 The following options are available to pagination control
554 <table id="zend.paginator.usage.rendering.properties.table">
555 <title>Properties available to view partials</title>
560 <entry>Property</entry>
562 <entry>Description</entry>
569 <entry>integer</entry>
570 <entry>First page number (i.e., 1)</entry>
574 <entry>firstItemNumber</entry>
575 <entry>integer</entry>
576 <entry>Absolute number of the first item on this page</entry>
580 <entry>firstPageInRange</entry>
581 <entry>integer</entry>
582 <entry>First page in the range returned by the scrolling style</entry>
586 <entry>current</entry>
587 <entry>integer</entry>
588 <entry>Current page number</entry>
592 <entry>currentItemCount</entry>
593 <entry>integer</entry>
594 <entry>Number of items on this page</entry>
598 <entry>itemCountPerPage</entry>
599 <entry>integer</entry>
600 <entry>Maximum number of items available to each page</entry>
605 <entry>integer</entry>
606 <entry>Last page number</entry>
610 <entry>lastItemNumber</entry>
611 <entry>integer</entry>
612 <entry>Absolute number of the last item on this page</entry>
616 <entry>lastPageInRange</entry>
617 <entry>integer</entry>
618 <entry>Last page in the range returned by the scrolling style</entry>
623 <entry>integer</entry>
624 <entry>Next page number</entry>
628 <entry>pageCount</entry>
629 <entry>integer</entry>
630 <entry>Number of pages</entry>
634 <entry>pagesInRange</entry>
636 <entry>Array of pages returned by the scrolling style</entry>
640 <entry>previous</entry>
641 <entry>integer</entry>
642 <entry>Previous page number</entry>
646 <entry>totalItemCount</entry>
647 <entry>integer</entry>
648 <entry>Total number of items</entry>