Разработчику. Сборник рецептов PHP
Задавайте вопросы

Постраничный вывод
большого количества записей

Вернуться назад

Задача

Необходимо отобразить на странице большой набор данных и обеспечить ссылки, позволяющие перемещаться по этому набору данных.

Решение

Здесь нужен PEAR класс DB_Pager:

require 'DB/Pager.php';

$offset = intval($_REQUEST['offset']);
$per_page = 3;

$sth = $dbh->query('SELECT * FROM zodiac ORDER BY id');
$pager = new DB_Pager($sth, $offset, $per_page);
$data = $pager->build();

// выводим на эту страницу каждую строку
while ($v = $pager->fetchRow()) {
     print "$v->sign, $v->symbol ($v->id)<br>";

}

// ссылка на предыдущую страницу
printf('<a href="%s?offset=%d>&lt;&lt;Prev</a> |',
          $_SERVER['PHP_SELF'],$data['prev']);

// прямая ссылка на каждую страницу
foreach ($data['pages'] as $page => $start) {
          printf(' <a href="%s?offset=%d">%d</a>
|',$_SERVER['PHP_SELF'],$start,$page);
}

// ссылка на следующую страницу
printf(' <a href="%s?offset=%d">Next&gt;&gt;</a>',
          $_SERVER['PHP_SELF'],$data['next']);

// показываем, какие записи находятся на данной странице
printf("<br>(Displaying %d - %d of %d)",
          $data['from'],$data['to'],$data['numrows']);

Если класса DB_Pager нет или вы не хотите его использовать, то можно реализовать свое собственное отображение индексированной ссылки с помощью функций pc_indexed_links() и pc_print_link()

$offset = intval($_REQUEST['offset']);
if (! $offset) { $offset = 1; }
$per_page = 5;
$total = $dbh >getOne('SELECT COUNT(*) FROM zodiac');

$sql = $dbh >modifyLimitQuery('SELECT * FROM zodiac ORDER BY id',
               $offset -1 ,$per_page);

$ar = $dbh->getAll($sql);
foreach ($ar as $k => $v) {
     print "$v->sign, $v->symbol ($v->id)<br>";

}

pc_indexed_links($total,$offset,$per_page);
printf("<br>(Displaying %d -% d of %d)",$offset,$offset+$k,$total);

Обсуждение

Класс DB_Pager разработан специально для постраничного отображения результатов запроса PEAR DB. Для того чтобы его использовать, создайте объект класса DB_Pager и укажите ему, какой запрос послать, какое смещение задать в начале результирующего множества, и какое количество элементов должно находиться на каждой странице. Это обеспечит корректное размещение информации по страницам.

Метод $pager->build() определяет возвращаемые строки и другие переменные, необходимые для конкретной страницы. Класс DB_Pager предоставляет метод fetchRow() для извлечения результатов, который работает таким же образом, как метод класса DB. (В классе DB_Pager можно также использовать метод fetchInto()). Однако, хоть он и предоставляет всю необходимую информацию для построения соответствующих ссылок, но оставляет вам собственно разработку этих ссылок. Начальное смещение предыдущей страницы находится в переменной $data['prev'], а переменная $data['next'] содержит начальное смещение следующей страницы. Массив $data['pages'] хранит номера страниц и их начальные смещения. Вывод для случая, когда переменная $offset равна 0, показан ниже:

Постраничный вывод с использованием класса DB_Pager

Все номера страниц, а также «<<Prev» и «Next>>» представляют собой ссылки. «<<Prev» и «1» указывают на текущую страницу; другие ссылки указывают на соответствующие страницы. На странице 4 ссылка «Next>>» указывает обратно на страницу 1. (Но ссылка «<<Prev» на странице 1 не указывает на страницу 4.) Номера в ссылках относятся к номерам страниц, а не к номерам элементов.

Если класс DB_Pager недоступен, то получить соответствующим образом отформатированные ссылки позволяют функции pc_print_link() и pc_indexed_links(), показанные в примерах описанных ниже:

pc_print_link()

function pc_print_link($inactive,$text,$offset=' ') {

      if ($inactive) {

printf('<font color="#666666">%s</font>',$text);
} else {
     printf('<a href="%soffset=%d">%s</a>',$_SERVER['PHP_SELF'],$offset,$text);
      }
}

pc_indexed_links()

function pc_indexed_links($total,$offset,$per_page) {
     $separator = ' | ';

     // выводим ссылку "<<Prev"
     pc_print_link($offset == 1, '&lt;&lt;Prev', $offset - $ per_page);

      // выводим все группировки, за исключением последней
     for ($start = 1, $end = $per_page;
          $end < $total;
          $start += $per_page, $end += $per_page) {

           print $separator;
          pc_print_link($offset == $start, "$start - $end", $start);

      }
     /* выводим последнюю группировку в этой точке переменная $start
      * указывает на элемент в начале последней группировки
      */

     /* текст толжен содержать диапазон, только если на последней
     * странице находится более одного элемента. Например,
     * последняя группировка из 11 элементов по 5 на каждой
      * странице должна показать просто "11", а не "11 11"
     */
     $end = ($total > $start) ? " - $total" : '';

      print $separator;
      pc_print_link($offset == $start, "$start$end", $start);

     // выводим ссылку "Next>>"
      print $separator;
     pc_print_link($offset == $start, 'Next&gt;&gt;',$offset + $per_page);

}

Применяя эти функции, извлеките соответствующее подмножество данных с помощью метода DB:: modifyLimitQuery() и выведите их. Для отображения индексированных ссылок вызовите функцию pc_indexed_links():

$offset = intval($_REQUEST['offset']);
if (! $offset) { $offset = 1; }
$per_page = 5;
$total = $dbh->getOne('SELECT COUNT(*) FROM zodiac');

$sql = $dbh->modifyLimitQuery('SELECT * FROM zodiac ORDER BY id',
               $offset 1,$per_page);
$ar = $dbh->getAll($sql);

foreach ($ar as $k => $v) {
     print "$v->sign, $v->symbol ($v->id)<br>";

}

pc_indexed_links($total,$offset,$per_page);
printf("<br>(Displaying %d - %d of %d)",$offset,$offset+$k,$total);

После соединения с базой данных необходимо убедиться, что переменная $offset имеет соответствующее значение. Переменная $offset представляет начальную запись в результирующем множестве, которое требуется отобразить. Чтобы стартовать с начала результирующего набора данных, надо установить переменную $offset в 1. В переменную $per_page заносится количество записей, отображаемых на каждой странице, а переменная $total представляет общее количество записей во всем результирующем множестве. В данном примере показываются все записи из таблицы Zodiac, поэтому переменной $total присваивается количество всех строк в таблице.

SQL-запрос, извлекающий данные в соответствующем порядке, имеет вид:

SELECT * FROM zodiac ORDER BY id

Для ограничения извлекаемых строк вызовите функцию modifyLimitQuery(). Чтобы извлечь $per_page строк, надо начинать с $offset - 1,поскольку первая строка в базе данных имеет номер 0, а не 1. Для ограничения строк, возвращаемых запросом, метод modifyLimitQuery() реализует корректный алгоритм, специфический для конкретной базы данных.

Выбранные строки извлекаются с помощью метода $dbh->getAll($sql), а затем отображается информация, содержащаяся в каждой строке. В конце каждой строки функция предоставляет навигационные ссылки. Вывод для случая, когда переменная $offset не установлена (или равна 1), показан на рис. ниже:

Постраничный вывод результатов, полученный с помощью функции pc_indexed_links()

На рисунках и «Next>>» представляют собой ссылки на одну и ту же страницу с заданными аргументами $offset, тогда как «<<Prev» и «1-5» не активны, поскольку то, на что они ссылаются, в настоящее время отображается.

Вернуться назад

Рейтинг@Mail.ru

Яндекс.Метрика

Индекс цитирования

Рейтинг Сайтов ДОСКИ.РУ