1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect1 id="zend.paginator.usage">
4 <title>Использование</title>
6 <sect2 id="zend.paginator.usage.paginating">
7 <title>Разбиение наборов данных на страницы </title>
10 Для разбиения наборов данных на страницы
11 <classname>Zend_Paginator</classname> должен иметь обобщенный
12 доступ к этим данным. Поэтому доступ к данным осуществляется
13 через адаптеры к источникам данных. В поставку Zend Framework
14 по умолчанию входят несколько адаптеров:
17 <table id="zend.paginator.usage.paginating.adapters">
18 <title>Адаптеры для Zend_Paginator</title>
23 <entry>Адаптер</entry>
24 <entry>Описание</entry>
30 <entry>Использует PHP-массив</entry>
33 <entry>DbSelect</entry>
35 Использует экземпляр <link
36 linkend="zend.db.select"><classname>Zend_Db_Select</classname></link>,
37 который будет возвращать массив
41 <entry>DbTableSelect</entry>
43 Использует экземпляр <link
44 linkend="zend.db.table.fetch-all"><classname>Zend_Db_Table_Select</classname></link>,
45 который будет возвращать объект
46 <classname>Zend_Db_Table_Rowset_Abstract</classname>.
47 Это дает возможность получить такую дополнительную
48 информацию, как, например, имена столбцов.
52 <entry>Iterator</entry>
55 <ulink url="http://www.php.net/~helly/php/ext/spl/interfaceIterator.html"><classname>Iterator</classname></ulink>
62 <classname>Zend_Paginator</classname> для разбиения
64 Но и в этом случае вы можете воспользоваться
65 возможностями постраничной навигации.
74 Вместо извлечения всех строк, соответствующих данному
75 запросу, адаптеры DbSelect and DbTableSelect извлекают
76 только тот объем данных, который необходим для отображения
81 Поэтому для определения общего количества соответствующих
82 запросу строк динамически генерируется второй запрос.
83 Но вы можете сами предоставить
84 адаптеру количество строк либо запрос для его определения.
85 См. метод <methodname>setRowCount()</methodname>
86 в адаптере DbSelect для получения более подробной информации.
91 При создании экземпляра класса
92 <classname>Zend_Paginator</classname> следует передавать адаптер его
96 <programlisting language="php"><![CDATA[
97 $paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($array));
101 Для удобства вы можете воспользоваться фабричным методом
102 <methodname>factory()</methodname> для получения адаптеров,
103 входящих в поставку Zend Framework:
106 <programlisting language="php"><![CDATA[
107 $paginator = Zend_Paginator::factory($array);
112 В случае использования адаптера Null вы должны передавать
113 его конструктору количество элементов вместо набора данных.
118 Несмотря на то, что на этом этапе экземпляр формально уже пригоден к
119 использованию, на практике вы должны будете еще
120 передавать номер страницы, запрошенный пользователем, чтобы он мог
121 просматривать данные:
124 <programlisting language="php"><![CDATA[
125 $paginator->setCurrentPageNumber($page);
129 Наиболее простым способом отслеживания номера страницы является
130 использование <acronym>URL</acronym>. Мы рекомендуем использовать
131 для этого совместимый с
132 <classname>Zend_Controller_Router_Interface</classname>
133 маршрутизатор, но это не является обязательным требованием.
137 Ниже приведен пример маршрута, который можно использовать в
138 конфигурационном файле <acronym>INI</acronym>:
141 <programlisting language="php"><![CDATA[
142 routes.example.route = articles/:articleName/:page
143 routes.example.defaults.controller = articles
144 routes.example.defaults.action = view
145 routes.example.defaults.page = 1
146 routes.example.reqs.articleName = \w+
147 routes.example.reqs.page = \d+
151 Используя этот маршрут и MVC-компоненты Zend Framework-а,
152 вы можете устанавливать номер текущей страницы следующим образом:
155 <programlisting language="php"><![CDATA[
156 $paginator->setCurrentPageNumber($this->_getParam('page'));
160 Есть также другие опции, о них читайте в разделе
161 <link linkend="zend.paginator.configuration">Конфигурация</link>.
165 После этого нужно присвоить экземпляр
166 <classname>Zend_Paginator</classname> переменной вида. Если
167 используется <classname>Zend_View</classname> с помощником
168 действий ViewRenderer, то для этого подходит следующий код:
171 <programlisting language="php"><![CDATA[
172 $this->view->paginator = $paginator;
176 <sect2 id="zend.paginator.usage.dbselect">
177 <title>Адаптеры DbSelect и DbTableSelect</title>
179 Хотя большинство адаптеров довольно просто в использовании, адаптеры
180 баз данных требуют дополнительных пояснений насчет извлечения
181 данных и подсчета количества строк.
185 При использовании адаптеры DbSelect и DbTableSelect
186 нет необходимости самостоятельно извлекать данные. Оба адаптера
187 сами выполняют извлечение данных и подсчет общего количества
188 страниц. Если полученные результаты выборки требуют дополнительной
189 обработки, то адаптер может быть расширен с переопределением
190 метода <methodname>getItems()</methodname>.
195 <emphasis>не</emphasis> извлекают все записи из базы данных для
196 того, чтобы посчитать их. Вместо этого адаптеры используют
197 исходный запрос для получения соответствующего COUNT-запроса,
198 этот запрос выполняется для получения общего количества строк.
199 Таким образом, производится еще один дополнительный запрос к базе
200 данных, но это во много раз быстрее, чем извлечение всего результата
201 и использование <methodname>count()</methodname>, особенно в случае
202 больших объемов данных.
206 Адаптеры баз данных будут пытаться строить наиболее эффективный
207 запрос, который будет выполняться практически на всех современных
208 СУРБД. Но в зависимости от используемой базы данных или даже
209 выбранной структуры могут быть более эффективные пути получения
211 На этот случай адаптеры баз данных дают возможность
212 устанавливать свой COUNT-запрос.
213 Например, если вы фиксируете количество постов в блоге в отдельной
214 таблице, то можете достичь более быстрого получения их
215 количества, написав следующий код:
218 <programlisting language="php"><![CDATA[
219 $adapter = new Zend_Paginator_Adapter_DbSelect($db->select()->from('posts'));
220 $adapter->setRowCount(
225 Zend_Paginator_Adapter_DbSelect::ROW_COUNT_COLUMN => 'post_count'
230 $paginator = new Zend_Paginator($adapter);
234 Этот подход может не дать большого выигрыша в производительности
235 в случае небольшого объема данных или простых запросов на
237 Однако в случае сложных запросов и больших объемов данных
238 подобный подход может дать значительный выигрыш
239 в производительности.
243 <sect2 id="zend.paginator.rendering">
244 <title>Рендеринг страниц через скрипты видов</title>
247 Для визуализации элементов страницы (если
248 вы используете для этого <classname>Zend_Paginator</classname>)
249 и отображения постраничной навигации используется скрипт вида.
253 Поскольку <classname>Zend_Paginator</classname> реализует
255 <ulink url="http://www.php.net/~helly/php/ext/spl/interfaceIteratorAggregate.html"><classname>IteratorAggregate</classname></ulink>,
256 то обход элементов и их отображение производится элементарно.
259 <programlisting language="php"><![CDATA[
263 <?php if (count($this->paginator)): ?>
265 <?php foreach ($this->paginator as $item): ?>
266 <li><?php echo $item; ?></li>
271 <?php echo $this->paginationControl($this->paginator,
273 'my_pagination_control.phtml'); ?>
279 Обратите внимание, что в конце вызывается помощник вида.
280 PaginationControl принимает экземпляр
281 <classname>Zend_Paginator</classname>, стиль прокрутки, скрипт
282 вида и массив дополнительных параметров.
286 Второй и третий параметры очень важны. В то время как скрипт вида
287 используется для определения <emphasis>внешнего вида</emphasis>
288 постраничной навигации, стиль прокрутки определяет ее
289 <emphasis>поведение</emphasis>.
290 Предположим, скрипт вида отображает постраничную навигацию
291 для результатов поиска следующего вида:
295 <inlinegraphic align="center" valign="middle"
296 fileref="figures/zend.paginator.usage.rendering.control.png"
301 Что должно происходить, если пользователь нажимает на ссылку "next"
302 несколько раз? Действительно, тут может быть сколько угодно
303 вариантов. Номер текущей страницы может оставаться в середине
304 (как это реализовано, например, в Yahoo!) или перемещаться к концу
305 ряда при каждом нажатии "next" и затем показываться снова с другого
306 конца. Количество отображаемых номеров страниц может даже
307 увеличиваться и уменьшаться, пока пользователь перемещается по ним
308 (или "прокручивает" их), как это сделано в Google.
312 Zend Framework предоставляет четыре стиля прокрутки:
315 <table id="zend.paginator.usage.rendering.scrolling-styles">
316 <title>Стили прокрутки для Zend_Paginator</title>
321 <entry>Стиль прокрутки</entry>
322 <entry>Описание</entry>
329 Возвращает все страницы. Полезен для
330 постраничной навигации в виде выпадающего списка
331 с относительно небольшим количеством страниц.
332 В этом случае предпочтительнее, чтобы в нем
333 отображались все доступные страницы.
337 <entry>Elastic</entry>
339 Скроллинг в стиле Google, в котором количество
340 отображаемых номеров страниц может увеличиваться и
341 уменьшаться, пока пользователь перемещается по
346 <entry>Jumping</entry>
348 Пока пользователь листает страницы, номер текущей
349 страницы перемещается к концу ряда и показывается
350 снова в начале нового ряда.
354 <entry>Sliding</entry>
356 Скроллинг в стиле Yahoo!, в котором номер текущей
357 страницы находится в середине ряда или настолько
358 близко к нему, насколько это возможно. Этот стиль
359 используется по умолчанию.
367 Четвертый и последний параметр предназначается для ассоциативного
368 массива дополнительных переменных, которые должны быть доступны в
369 вашем скрипте вида (через <varname>$this</varname>).
370 Например, эти значения могут включать в себя дополнительные
371 параметры <acronym>URL</acronym> для подстановки в ссылки
372 постраничной навигации.
376 Установив используемые по умолчанию скрипт вида, стиль прокрутки и
377 экземпляр вида, вы можете полностью исключить вызовы
381 <programlisting language="php"><![CDATA[
382 Zend_Paginator::setDefaultScrollingStyle('Sliding');
383 Zend_View_Helper_PaginationControl::setDefaultViewPartial(
384 'my_pagination_control.phtml'
386 $paginator->setView($view);
390 Если все эти значения установлены, то вы можете вывести
391 постраничную навигацию в своем скрипте вида с помощью обычной
395 <programlisting language="php"><![CDATA[
396 <?php echo $this->paginator; ?>
401 Разумеется, можно использовать
402 <classname>Zend_Paginator</classname> с другими
403 шаблонизаторами. Например, со Smarty вы можете делать
407 <programlisting language="php"><![CDATA[
408 $smarty->assign('pages', $paginator->getPages());
412 Вы можете затем обращаться к установленным значениям из
413 шаблона, как в коде ниже:
416 <programlisting language="php"><![CDATA[
421 <sect3 id="zend.paginator.usage.rendering.example-controls">
422 <title>Примеры постраничной навигации</title>
425 Надеемся, следующие примеры помогут начать работать с
426 <classname>Zend_Paginator</classname>:
430 Постраничная навигация для результатов поиска:
433 <programlisting language="php"><![CDATA[
435 См. http://developer.yahoo.com/ypatterns/pattern.php?pattern=searchpagination
438 <?php if ($this->pageCount): ?>
439 <div class="paginationControl">
440 <!-- Ссылка на предыдущую страницу -->
441 <?php if (isset($this->previous)): ?>
442 <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
446 <span class="disabled">< Previous</span> |
449 <!-- Нумерованные ссылки на страницы -->
450 <?php foreach ($this->pagesInRange as $page): ?>
451 <?php if ($page != $this->current): ?>
452 <a href="<?php echo $this->url(array('page' => $page)); ?>">
456 <?php echo $page; ?> |
460 <!-- Ссылка на следующую страницу -->
461 <?php if (isset($this->next)): ?>
462 <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
466 <span class="disabled">Next ></span>
473 Постраничная навигация для элементов:
476 <programlisting language="php"><![CDATA[
478 См. http://developer.yahoo.com/ypatterns/pattern.php?pattern=itempagination
481 <?php if ($this->pageCount): ?>
482 <div class="paginationControl">
483 <?php echo $this->firstItemNumber; ?> - <?php echo $this->lastItemNumber; ?>
484 of <?php echo $this->totalItemCount; ?>
486 <!-- Ссылка на первую страницу -->
487 <?php if (isset($this->previous)): ?>
488 <a href="<?php echo $this->url(array('page' => $this->first)); ?>">
492 <span class="disabled">First</span> |
495 <!-- Ссылка на предыдущую страницу -->
496 <?php if (isset($this->previous)): ?>
497 <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
501 <span class="disabled">< Previous</span> |
504 <!-- Ссылка на следующую страницу -->
505 <?php if (isset($this->next)): ?>
506 <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
510 <span class="disabled">Next ></span> |
513 <!-- Ссылка на последнюю страницу -->
514 <?php if (isset($this->next)): ?>
515 <a href="<?php echo $this->url(array('page' => $this->last)); ?>">
519 <span class="disabled">Last</span>
527 Постраничная навигация в виде выпадающего списка:
530 <programlisting language="php"><![CDATA[
531 <?php if ($this->pageCount): ?>
532 <select id="paginationControl" size="1">
533 <?php foreach ($this->pagesInRange as $page): ?>
534 <?php $selected = ($page == $this->current) ? ' selected="selected"' : ''; ?>
536 echo $this->url(array('page' => $page));?>"<?php echo $selected ?>>
543 <script type="text/javascript"
544 src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js">
546 <script type="text/javascript">
547 $('paginationControl').observe('change', function() {
548 window.location = this.options[this.selectedIndex].value;
554 <sect3 id="zend.paginator.usage.rendering.properties">
555 <title>Список свойств</title>
558 Следующие опции доступны внутри скрипта вида для постраничной
562 <table id="zend.paginator.usage.rendering.properties.table">
563 <title>Свойства, доступные в скрипте вида</title>
568 <entry>Свойство</entry>
570 <entry>Описание</entry>
576 <entry>integer</entry>
577 <entry>Номер первой страницы (т.е. 1)</entry>
580 <entry>firstItemNumber</entry>
581 <entry>integer</entry>
583 Действительный номер первого элемента на
588 <entry>firstPageInRange</entry>
589 <entry>integer</entry>
591 Первая страница в ряде, возвращенном текущим
596 <entry>current</entry>
597 <entry>integer</entry>
598 <entry>Текущий номер страницы</entry>
601 <entry>currentItemCount</entry>
602 <entry>integer</entry>
603 <entry>Количество элементов на текущей странице</entry>
606 <entry>itemCountPerPage</entry>
607 <entry>integer</entry>
609 Максимальное количество отображаемых
610 на странице элементов
615 <entry>integer</entry>
616 <entry>Номер последней страницы</entry>
619 <entry>lastItemNumber</entry>
620 <entry>integer</entry>
622 Действительный номер последнего элемента на
627 <entry>lastPageInRange</entry>
628 <entry>integer</entry>
630 Последняя страница в ряде, возвращенном текущим
636 <entry>integer</entry>
637 <entry>Номер следующей страницы</entry>
640 <entry>pageCount</entry>
641 <entry>integer</entry>
642 <entry>Общее количество страниц</entry>
645 <entry>pagesInRange</entry>
648 Массив страниц, возвращенный текущим стилем
653 <entry>previous</entry>
654 <entry>integer</entry>
655 <entry>Номер предыдущей страницы</entry>
658 <entry>totalItemCount</entry>
659 <entry>integer</entry>
660 <entry>Общее количество элементов</entry>