1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
|
<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.paginator.advanced">
<title>Advanced usage</title>
<sect2 id="zend.paginator.advanced.adapters">
<title>Custom data source adapters</title>
<para>
At some point you may run across a data type that is not covered by
the packaged adapters. In this case, you will need to write your
own.
</para>
<para>
To do so, you must implement
<classname>Zend_Paginator_Adapter_Interface</classname>. There are two
methods required to do this:
</para>
<itemizedlist>
<listitem>
<para>count()</para>
</listitem>
<listitem>
<para>getItems($offset, $itemCountPerPage)</para>
</listitem>
</itemizedlist>
<para>
Additionally, you'll want to implement a constructor that takes
your data source as a parameter and stores it as a protected or
private property. How you wish to go about doing this
specifically is up to you.
</para>
<para>
If you've ever used the SPL interface <ulink
url="http://www.php.net/~helly/php/ext/spl/interfaceCountable.html">Countable</ulink>,
you're familiar with <methodname>count()</methodname>. As used with
<classname>Zend_Paginator</classname>, this is the total number of items
in the data collection.
Additionally, the <classname>Zend_Paginator</classname> instance provides a method
<methodname>countAllItems()</methodname> that proxies to the adapter
<methodname>count()</methodname> method.
</para>
<para>
The <methodname>getItems()</methodname> method is only slightly more
complicated. For this, your adapter is supplied with an offset and
the number of items to display per page. You must return the
appropriate slice of data. For an array, that would be:
</para>
<programlisting language="php"><![CDATA[
return array_slice($this->_array, $offset, $itemCountPerPage);
]]></programlisting>
<para>
Take a look at the packaged adapters (all of which implement the
<classname>Zend_Paginator_Adapter_Interface</classname>) for ideas of how you
might go about implementing your own.
</para>
</sect2>
<sect2 id="zend.paginator.advanced.scrolling-styles">
<title>Custom scrolling styles</title>
<para>
Creating your own scrolling style requires that you implement
<classname>Zend_Paginator_ScrollingStyle_Interface</classname>, which defines
a single method, <methodname>getPages()</methodname>. Specifically,
</para>
<programlisting language="php"><![CDATA[
public function getPages(Zend_Paginator $paginator, $pageRange = null);
]]></programlisting>
<para>
This method should calculate a lower and upper bound for page
numbers within the range of so-called "local" pages (that is, pages
that are nearby the current page).
</para>
<para>
Unless it extends another scrolling style (see
<classname>Zend_Paginator_ScrollingStyle_Elastic</classname> for an example),
your custom scrolling style will inevitably end with something
similar to the following line of code:
</para>
<programlisting language="php"><![CDATA[
return $paginator->getPagesInRange($lowerBound, $upperBound);
]]></programlisting>
<para>
There's nothing special about this call; it's merely a convenience
method to check the validity of the lower and upper bound and
return an array of the range to the paginator.
</para>
<para>
When you're ready to use your new scrolling style, you'll need to
tell <classname>Zend_Paginator</classname> what directory to look in. To do
that, do the following:
</para>
<programlisting language="php"><![CDATA[
$prefix = 'My_Paginator_ScrollingStyle';
$path = 'My/Paginator/ScrollingStyle/';
Zend_Paginator::addScrollingStylePrefixPath($prefix, $path);
]]></programlisting>
</sect2>
<sect2 id="zend.paginator.advanced.caching">
<title>Caching features</title>
<para>
<classname>Zend_Paginator</classname> can be told to cache the data it has already
passed on, preventing the adapter from fetching them each time they are used.
To tell paginator to automatically cache the adapter's data, just pass to
its <methodname>setCache()</methodname> method a <classname>Zend_Cache_Core</classname>
instance.
</para>
<programlisting language="php"><![CDATA[
$paginator = Zend_Paginator::factory($someData);
$fO = array('lifetime' => 3600, 'automatic_serialization' => true);
$bO = array('cache_dir'=>'/tmp');
$cache = Zend_cache::factory('Core', 'File', $fO, $bO);
Zend_Paginator::setCache($cache);
]]></programlisting>
<para>
As far as <classname>Zend_Paginator</classname> has got a
<classname>Zend_Cache_Core</classname> instance, data will be cached. Sometimes you
would like not to cache data even if you already passed a cache instance. You should
then use <methodname>setCacheEnable()</methodname> for that.
</para>
<programlisting language="php"><![CDATA[
$paginator = Zend_Paginator::factory($someData);
// $cache is a Zend_Cache_Core instance
Zend_Paginator::setCache($cache);
// ... later on the script
$paginator->setCacheEnable(false);
// cache is now disabled
]]></programlisting>
<para>
When a cache is set, data are automatically stored in it and pulled out from
it. It then can be useful to empty the cache manually. You can get this done by
calling <methodname>clearPageItemCache($pageNumber)</methodname>.
If you don't pass any parameter, the whole cache will be empty. You can optionally
pass a parameter representing the page number to empty in the cache:
</para>
<programlisting language="php"><![CDATA[
$paginator = Zend_Paginator::factory($someData);
Zend_Paginator::setCache($cache);
$items = $paginator->getCurrentItems();
// page 1 is now in cache
$page3Items = $paginator->getItemsByPage(3);
// page 3 is now in cache
// clear the cache of the results for page 3
$paginator->clearPageItemCache(3);
// clear all the cache data
$paginator->clearPageItemCache();
]]></programlisting>
<para>
Changing the item count per page will empty the whole cache
as it would have become invalid:
</para>
<programlisting language="php"><![CDATA[
$paginator = Zend_Paginator::factory($someData);
Zend_Paginator::setCache($cache);
// fetch some items
$items = $paginator->getCurrentItems();
// all the cache data will be flushed:
$paginator->setItemCountPerPage(2);
]]></programlisting>
<para>
It is also possible to see the data in cache and ask for them directly.
<methodname>getPageItemCache()</methodname> can be used for that:
</para>
<programlisting language="php"><![CDATA[
$paginator = Zend_Paginator::factory($someData);
$paginator->setItemCountPerPage(3);
Zend_Paginator::setCache($cache);
// fetch some items
$items = $paginator->getCurrentItems();
$otherItems = $paginator->getItemsPerPage(4);
// see the cached items as a two-dimension array:
var_dump($paginator->getPageItemCache());
]]></programlisting>
</sect2>
<sect2 id="zend.paginator.advanced.aggregator">
<title>Zend_Paginator_AdapterAggregate Interface</title>
<para>
Depending on your application you might want to paginate objects, whose internal
data-structure is equal to existing adapters, but you don't want to break up your
encapsulation to allow access to this data. In other cases an object might be in a
"has-an adapter" relationship, rather than the "is-an adapter" relationsship that
<classname>Zend_Paginator_Adapter_Abstract</classname> promotes. For this cases you can
use the <classname>Zend_Paginator_AdapterAggregate</classname> interface that behaves
much like the <classname>IteratorAggregate</classname> interface of the
<acronym>PHP</acronym> SPL extension.
</para>
<programlisting language="php"><![CDATA[
interface Zend_Paginator_AdapterAggregate
{
/**
* Return a fully configured Paginator Adapter from this method.
*
* @return Zend_Paginator_Adapter_Abstract
*/
public function getPaginatorAdapter();
}
]]></programlisting>
<para>
The interface is fairly small and only expects you to return an instance of
<classname>Zend_Paginator_Adapter_Abstract</classname>. An Adapter Aggregate instance is
then recognized by both <methodname>Zend_Paginator::factory()</methodname> and the
constructor of <classname>Zend_Paginator</classname> and handled accordingly.
</para>
</sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
|