| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.paginator.usage">
- <title>Использование</title>
- <sect2 id="zend.paginator.usage.paginating">
- <title>Разбиение наборов данных на страницы </title>
- <para>
- Для разбиения наборов данных на страницы
- <classname>Zend_Paginator</classname> должен иметь обобщенный
- доступ к этим данным. Поэтому доступ к данным осуществляется
- через адаптеры к источникам данных. В поставку Zend Framework
- по умолчанию входят несколько адаптеров:
- </para>
- <table id="zend.paginator.usage.paginating.adapters">
- <title>Адаптеры для Zend_Paginator</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Адаптер</entry>
- <entry>Описание</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>Array</entry>
- <entry>Использует PHP-массив</entry>
- </row>
- <row>
- <entry>DbSelect</entry>
- <entry>
- Использует экземпляр <link
- linkend="zend.db.select"><classname>Zend_Db_Select</classname></link>,
- который будет возвращать массив
- </entry>
- </row>
- <row>
- <entry>DbTableSelect</entry>
- <entry>
- Использует экземпляр <link
- linkend="zend.db.table.fetch-all"><classname>Zend_Db_Table_Select</classname></link>,
- который будет возвращать объект
- <classname>Zend_Db_Table_Rowset_Abstract</classname>.
- Это дает возможность получить такую дополнительную
- информацию, как, например, имена столбцов.
- </entry>
- </row>
- <row>
- <entry>Iterator</entry>
- <entry>
- Использует экземпляр
- <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> для разбиения
- на страницы.
- Но и в этом случае вы можете воспользоваться
- возможностями постраничной навигации.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <note>
- <para>
- Вместо извлечения всех строк, соответствующих данному
- запросу, адаптеры DbSelect and DbTableSelect извлекают
- только тот объем данных, который необходим для отображения
- текущей страницы.
- </para>
- <para>
- Поэтому для определения общего количества соответствующих
- запросу строк динамически генерируется второй запрос.
- Но вы можете сами предоставить
- адаптеру количество строк либо запрос для его определения.
- См. метод <methodname>setRowCount()</methodname>
- в адаптере DbSelect для получения более подробной информации.
- </para>
- </note>
- <para>
- При создании экземпляра класса
- <classname>Zend_Paginator</classname> следует передавать адаптер его
- конструктору:
- </para>
- <programlisting language="php"><![CDATA[
- $paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($array));
- ]]></programlisting>
- <para>
- Для удобства вы можете воспользоваться фабричным методом
- <methodname>factory()</methodname> для получения адаптеров,
- входящих в поставку Zend Framework:
- </para>
- <programlisting language="php"><![CDATA[
- $paginator = Zend_Paginator::factory($array);
- ]]></programlisting>
- <note>
- <para>
- В случае использования адаптера Null вы должны передавать
- его конструктору количество элементов вместо набора данных.
- </para>
- </note>
- <para>
- Несмотря на то, что на этом этапе экземпляр формально уже пригоден к
- использованию, на практике вы должны будете еще
- передавать номер страницы, запрошенный пользователем, чтобы он мог
- просматривать данные:
- </para>
- <programlisting language="php"><![CDATA[
- $paginator->setCurrentPageNumber($page);
- ]]></programlisting>
- <para>
- Наиболее простым способом отслеживания номера страницы является
- использование <acronym>URL</acronym>. Мы рекомендуем использовать
- для этого совместимый с
- <classname>Zend_Controller_Router_Interface</classname>
- маршрутизатор, но это не является обязательным требованием.
- </para>
- <para>
- Ниже приведен пример маршрута, который можно использовать в
- конфигурационном файле <acronym>INI</acronym>:
- </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>
- Используя этот маршрут и MVC-компоненты Zend Framework-а,
- вы можете устанавливать номер текущей страницы следующим образом:
- </para>
- <programlisting language="php"><![CDATA[
- $paginator->setCurrentPageNumber($this->_getParam('page'));
- ]]></programlisting>
- <para>
- Есть также другие опции, о них читайте в разделе
- <link linkend="zend.paginator.configuration">Конфигурация</link>.
- </para>
- <para>
- После этого нужно присвоить экземпляр
- <classname>Zend_Paginator</classname> переменной вида. Если
- используется <classname>Zend_View</classname> с помощником
- действий ViewRenderer, то для этого подходит следующий код:
- </para>
- <programlisting language="php"><![CDATA[
- $this->view->paginator = $paginator;
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.paginator.usage.dbselect">
- <title>Адаптеры DbSelect и DbTableSelect</title>
- <para>
- Хотя большинство адаптеров довольно просто в использовании, адаптеры
- баз данных требуют дополнительных пояснений насчет извлечения
- данных и подсчета количества строк.
- </para>
- <para>
- При использовании адаптеры DbSelect и DbTableSelect
- нет необходимости самостоятельно извлекать данные. Оба адаптера
- сами выполняют извлечение данных и подсчет общего количества
- страниц. Если полученные результаты выборки требуют дополнительной
- обработки, то адаптер может быть расширен с переопределением
- метода <methodname>getItems()</methodname>.
- </para>
- <para>
- Эти адаптеры
- <emphasis>не</emphasis> извлекают все записи из базы данных для
- того, чтобы посчитать их. Вместо этого адаптеры используют
- исходный запрос для получения соответствующего COUNT-запроса,
- этот запрос выполняется для получения общего количества строк.
- Таким образом, производится еще один дополнительный запрос к базе
- данных, но это во много раз быстрее, чем извлечение всего результата
- и использование <methodname>count()</methodname>, особенно в случае
- больших объемов данных.
- </para>
- <para>
- Адаптеры баз данных будут пытаться строить наиболее эффективный
- запрос, который будет выполняться практически на всех современных
- СУРБД. Но в зависимости от используемой базы данных или даже
- выбранной структуры могут быть более эффективные пути получения
- количества строк.
- На этот случай адаптеры баз данных дают возможность
- устанавливать свой COUNT-запрос.
- Например, если вы фиксируете количество постов в блоге в отдельной
- таблице, то можете достичь более быстрого получения их
- количества, написав следующий код:
- </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>
- Этот подход может не дать большого выигрыша в производительности
- в случае небольшого объема данных или простых запросов на
- извлечение.
- Однако в случае сложных запросов и больших объемов данных
- подобный подход может дать значительный выигрыш
- в производительности.
- </para>
- </sect2>
- <sect2 id="zend.paginator.rendering">
- <title>Рендеринг страниц через скрипты видов</title>
- <para>
- Для визуализации элементов страницы (если
- вы используете для этого <classname>Zend_Paginator</classname>)
- и отображения постраничной навигации используется скрипт вида.
- </para>
- <para>
- Поскольку <classname>Zend_Paginator</classname> реализует
- SPL-интерфейс
- <ulink url="http://www.php.net/~helly/php/ext/spl/interfaceIteratorAggregate.html"><classname>IteratorAggregate</classname></ulink>,
- то обход элементов и их отображение производится элементарно.
- </para>
- <programlisting language="php"><![CDATA[
- <html>
- <body>
- <h1>Example</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>
- Обратите внимание, что в конце вызывается помощник вида.
- PaginationControl принимает экземпляр
- <classname>Zend_Paginator</classname>, стиль прокрутки, скрипт
- вида и массив дополнительных параметров.
- </para>
- <para>
- Второй и третий параметры очень важны. В то время как скрипт вида
- используется для определения <emphasis>внешнего вида</emphasis>
- постраничной навигации, стиль прокрутки определяет ее
- <emphasis>поведение</emphasis>.
- Предположим, скрипт вида отображает постраничную навигацию
- для результатов поиска следующего вида:
- </para>
- <para>
- <inlinegraphic align="center" valign="middle"
- fileref="figures/zend.paginator.usage.rendering.control.png"
- format="PNG"/>
- </para>
- <para>
- Что должно происходить, если пользователь нажимает на ссылку "next"
- несколько раз? Действительно, тут может быть сколько угодно
- вариантов. Номер текущей страницы может оставаться в середине
- (как это реализовано, например, в Yahoo!) или перемещаться к концу
- ряда при каждом нажатии "next" и затем показываться снова с другого
- конца. Количество отображаемых номеров страниц может даже
- увеличиваться и уменьшаться, пока пользователь перемещается по ним
- (или "прокручивает" их), как это сделано в Google.
- </para>
- <para>
- Zend Framework предоставляет четыре стиля прокрутки:
- </para>
- <table id="zend.paginator.usage.rendering.scrolling-styles">
- <title>Стили прокрутки для Zend_Paginator</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Стиль прокрутки</entry>
- <entry>Описание</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>All</entry>
- <entry>
- Возвращает все страницы. Полезен для
- постраничной навигации в виде выпадающего списка
- с относительно небольшим количеством страниц.
- В этом случае предпочтительнее, чтобы в нем
- отображались все доступные страницы.
- </entry>
- </row>
- <row>
- <entry>Elastic</entry>
- <entry>
- Скроллинг в стиле Google, в котором количество
- отображаемых номеров страниц может увеличиваться и
- уменьшаться, пока пользователь перемещается по
- страницам.
- </entry>
- </row>
- <row>
- <entry>Jumping</entry>
- <entry>
- Пока пользователь листает страницы, номер текущей
- страницы перемещается к концу ряда и показывается
- снова в начале нового ряда.
- </entry>
- </row>
- <row>
- <entry>Sliding</entry>
- <entry>
- Скроллинг в стиле Yahoo!, в котором номер текущей
- страницы находится в середине ряда или настолько
- близко к нему, насколько это возможно. Этот стиль
- используется по умолчанию.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>
- Четвертый и последний параметр предназначается для ассоциативного
- массива дополнительных переменных, которые должны быть доступны в
- вашем скрипте вида (через <varname>$this</varname>).
- Например, эти значения могут включать в себя дополнительные
- параметры <acronym>URL</acronym> для подстановки в ссылки
- постраничной навигации.
- </para>
- <para>
- Установив используемые по умолчанию скрипт вида, стиль прокрутки и
- экземпляр вида, вы можете полностью исключить вызовы
- PaginationControl:
- </para>
- <programlisting language="php"><![CDATA[
- Zend_Paginator::setDefaultScrollingStyle('Sliding');
- Zend_View_Helper_PaginationControl::setDefaultViewPartial(
- 'my_pagination_control.phtml'
- );
- $paginator->setView($view);
- ]]></programlisting>
- <para>
- Если все эти значения установлены, то вы можете вывести
- постраничную навигацию в своем скрипте вида с помощью обычной
- конструкции echo:
- </para>
- <programlisting language="php"><![CDATA[
- <?php echo $this->paginator; ?>
- ]]></programlisting>
- <note>
- <para>
- Разумеется, можно использовать
- <classname>Zend_Paginator</classname> с другими
- шаблонизаторами. Например, со Smarty вы можете делать
- следующее:
- </para>
- <programlisting language="php"><![CDATA[
- $smarty->assign('pages', $paginator->getPages());
- ]]></programlisting>
- <para>
- Вы можете затем обращаться к установленным значениям из
- шаблона, как в коде ниже:
- </para>
- <programlisting language="php"><![CDATA[
- {$pages->pageCount}
- ]]></programlisting>
- </note>
- <sect3 id="zend.paginator.usage.rendering.example-controls">
- <title>Примеры постраничной навигации</title>
- <para>
- Надеемся, следующие примеры помогут начать работать с
- <classname>Zend_Paginator</classname>:
- </para>
- <para>
- Постраничная навигация для результатов поиска:
- </para>
- <programlisting language="php"><![CDATA[
- <!--
- См. http://developer.yahoo.com/ypatterns/pattern.php?pattern=searchpagination
- -->
- <?php if ($this->pageCount): ?>
- <div class="paginationControl">
- <!-- Ссылка на предыдущую страницу -->
- <?php if (isset($this->previous)): ?>
- <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
- < Previous
- </a> |
- <?php else: ?>
- <span class="disabled">< Previous</span> |
- <?php endif; ?>
- <!-- Нумерованные ссылки на страницы -->
- <?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; ?>
- <!-- Ссылка на следующую страницу -->
- <?php if (isset($this->next)): ?>
- <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
- Next >
- </a>
- <?php else: ?>
- <span class="disabled">Next ></span>
- <?php endif; ?>
- </div>
- <?php endif; ?>
- ]]></programlisting>
- <para>
- Постраничная навигация для элементов:
- </para>
- <programlisting language="php"><![CDATA[
- <!--
- См. 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; ?>
- <!-- Ссылка на первую страницу -->
- <?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; ?>
- <!-- Ссылка на предыдущую страницу -->
- <?php if (isset($this->previous)): ?>
- <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
- < Previous
- </a> |
- <?php else: ?>
- <span class="disabled">< Previous</span> |
- <?php endif; ?>
- <!-- Ссылка на следующую страницу -->
- <?php if (isset($this->next)): ?>
- <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
- Next >
- </a> |
- <?php else: ?>
- <span class="disabled">Next ></span> |
- <?php endif; ?>
- <!-- Ссылка на последнюю страницу -->
- <?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>
- Постраничная навигация в виде выпадающего списка:
- </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>Список свойств</title>
- <para>
- Следующие опции доступны внутри скрипта вида для постраничной
- навигации:
- </para>
- <table id="zend.paginator.usage.rendering.properties.table">
- <title>Свойства, доступные в скрипте вида</title>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Свойство</entry>
- <entry>Тип</entry>
- <entry>Описание</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>first</entry>
- <entry>integer</entry>
- <entry>Номер первой страницы (т.е. 1)</entry>
- </row>
- <row>
- <entry>firstItemNumber</entry>
- <entry>integer</entry>
- <entry>
- Действительный номер первого элемента на
- текущей странице
- </entry>
- </row>
- <row>
- <entry>firstPageInRange</entry>
- <entry>integer</entry>
- <entry>
- Первая страница в ряде, возвращенном текущим
- стилем прокрутки
- </entry>
- </row>
- <row>
- <entry>current</entry>
- <entry>integer</entry>
- <entry>Текущий номер страницы</entry>
- </row>
- <row>
- <entry>currentItemCount</entry>
- <entry>integer</entry>
- <entry>Количество элементов на текущей странице</entry>
- </row>
- <row>
- <entry>itemCountPerPage</entry>
- <entry>integer</entry>
- <entry>
- Максимальное количество отображаемых
- на странице элементов
- </entry>
- </row>
- <row>
- <entry>last</entry>
- <entry>integer</entry>
- <entry>Номер последней страницы</entry>
- </row>
- <row>
- <entry>lastItemNumber</entry>
- <entry>integer</entry>
- <entry>
- Действительный номер последнего элемента на
- текущей странице
- </entry>
- </row>
- <row>
- <entry>lastPageInRange</entry>
- <entry>integer</entry>
- <entry>
- Последняя страница в ряде, возвращенном текущим
- стилем прокрутки
- </entry>
- </row>
- <row>
- <entry>next</entry>
- <entry>integer</entry>
- <entry>Номер следующей страницы</entry>
- </row>
- <row>
- <entry>pageCount</entry>
- <entry>integer</entry>
- <entry>Общее количество страниц</entry>
- </row>
- <row>
- <entry>pagesInRange</entry>
- <entry>array</entry>
- <entry>
- Массив страниц, возвращенный текущим стилем
- прокрутки
- </entry>
- </row>
- <row>
- <entry>previous</entry>
- <entry>integer</entry>
- <entry>Номер предыдущей страницы</entry>
- </row>
- <row>
- <entry>totalItemCount</entry>
- <entry>integer</entry>
- <entry>Общее количество элементов</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </sect3>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|