|
Pers.narod.ru. PHP. Разбиваем вывод PHP на страницы |
На большинстве сайтов нужно выдавать пользователю полученные из базы данные небольшими "порциями" по 10, 20 или ещё сколько-то записей. Чаще всего при этом внизу или вверху страницы доступно меню, позволяющее перейти к другой странице:

Когда страниц много, переходить между ними становится не очень удобно, а меню перехода разрастается и занимает всё больше места, как, например, в этой гостевой на Narod.Ru:

Давайте кратко обсудим, как в коде на PHP делать разбиение на страницы, и напишем соответствующую "универсальную" функцию.
Во-первых, нам понадобится ряд переменных, управляющих отображением данных. Я обычно обхожусь примерно таким набором:
$sort - способ сортировки записей; если предумсотрены прямая и обратная сортировка, может понадобиться еще и переменная, управляющая режимом сортировки;
$start - начиная с какой записи отображать;
$limit - по сколько записей отображать; удобно, если специально назначенное значение этой переменной (например, -1) говорит о том, что надо отобразить все записи.
Где хранить все эти переменные? В 5-й (да и 4-й) версиях PHP уже не стоит объявлять глобальных переменных. Передавать все данные через URL запроса - тоже можно, хотя это неудобно и создает длинные неудобочитаемые адреса:
http://мойсайт.ru/index.php?id=8&sort=date&start=0&limit=5
Кроме того, при таком подходе придется "таскать" все эти переменные из скрипта в скрипт, добавляя в каждый файл обработку соответствующих параметров (кстати, о компактной обработке параметров, переданных через GET или POST, написано в этой статье).
В качестве альтернативы можно хранить все переменные, отвечающие за настройки вывода, в созданной браузером сессии. Для этого достаточно первой строчкой каждого скрипта указать вызов функции, запускающей сессию:
session_start ();
Второй строкой можно всегда указывать подключение файла functions.php с функциями проекта:
require_once ("functions.php");
Этот файл, в свою очередь, может подключать другие библиотеки, например, файл конфигурации проекта и бибилиотеку для работы с базой данных:
require_once ("config.php");
require_once ("db.php");
...
Несложный пример библиотеки db.php описан, например, в этой статье, а про поддержку сессий говорится в этой.
Сделав простейшие файлы, отвечающие за переключение режимов вывода (скажем, вот файл sort.php, позволяющий последовательно переключать переменную сессии $sort между значениями date, rating и title):
<?
session_start();
require_once ("functions.php");
if ($_SESSION['sort']=='date') $_SESSION['sort']='rating';
else if ($_SESSION['sort']=='rating') $_SESSION['sort']='title';
else $_SESSION['sort']='date';
if (isset ($_SERVER['HTTP_REFERER'])) {
header('Location: '.$_SERVER['HTTP_REFERER']);
}
else {
header('Location: index.php');
}
?>
и поставив ссылки на эти файлы где-нибудь в единой для всего портала "шапке" страниц:
<p>Сортировать по: <a href="sort.php"><?print ($_SESSION['sort']=='date'? 'рейтингу':($_SESSION['sort']=='rating'?'заголовку':'дате')); ?></a> Выводить по: <a href="limits.php?limit=10">10</a> <a href="limits.php?limit=50">50</a> <a href="limits.php?limit=-1">все</a>
мы можем теперь переключать режимы вывода с любой страницы сайта, не передавая никаких лишних переменных скриптам. Здесь предполагается, что названия режимов сортировки совпадают с именами полей в таблице БД, то есть, в таблице имеются поля с именами title, date и rating, по которым её можно сортировать.
Дать переменным сессии начальные значения можно в любом коде, выполняемом один раз, скажем, так:
if (empty($_SESSION['sort'])) $_SESSION['sort']='date'; if (empty($_SESSION['start'])) $_SESSION['start']='0'; if (empty($_SESSION['limit'])) $_SESSION['limit']='10';
Дело за малым - получив из базы данных список страниц, отвечающих запросу, сформировать меню для их вывода.
В качестве примера предположим, что данные хранятся в таблице с именем notes, тогда SQL-запрос и его обработка могут иметь следующий вид:
$sql='select * from notes order by '.$_SESSION['sort'].' desc';
if ($_SESSION['limit']!=-1) $sql.=' limit '.$_SESSION['start'].','.$_SESSION['limit'];
$result = dbquery($sql);
if ($result and dbrows($result)) {
while ($page = dbfetcha($result)) {
/*
Разбор и вывод очередной статьи. Поле базы с именем text
будет доступно как $page['text'] и т.д.
*/
}
if ($_SESSION['limit']>-1) {
$count = dbfetch(dbquery("select count(*) from notes"));
if ($count[0]>$_SESSION['limit']) {
print '<p align=center>';
navigation_string ($count[0],$_SESSION['sort'],
$_SESSION['start'],$_SESSION['limit']);
print "</p>\n";
}
}
}
else {
/* Обработка ситуации, когда не удалось получить ни одной статьи */
}
Здесь для простоты всегда делается сортировка по убыванию (desc), а число записей в базе получается отдельным запросом select count(*) from notes, в жизни того и другого легко избежать. Функция navigation_string, тело которой помещено в файл функций functions.php, выполнит всю работу:
function navigation_string ($count,$sort,$start,$limit) {
if ($count>$limit) {
$show=false;
for ($s=0; $s<$count; $s+=$limit) {
$from=$s+1;
$to=$from+$limit-1;
if ($to>$count) $to=$count;
if ($from==$to) $diap="$from";
else $diap="$from-$to";
if ( (abs($s-$start)<2*$limit) or ($s<2*$limit) or ($s>=$count-2*$limit) ) {
if ($s!=$start) print
" [<a href=\"start.php?start=$s\">$diap</a>]";
else print " [$diap]";
$show=true;
}
else {
if ($show) { print " ..."; $show=false; }
}
}
//Если не нужна ссылка для вывода всех страниц - закомментарить строку ниже
print " [<a href=\"limits.php?limit=-1\">все</a>]";
}
}Здесь для изменения настройки разбиения на порции вызывается скрипт start.php:
<?
session_start();
require_once ("functions.php");
$params = array('start');
require_once ("params.php");
if ($start<0) $start=0;
$_SESSION['start']=$start;
if (isset ($_SERVER['HTTP_REFERER'])) {
header('Location: '.$_SERVER['HTTP_REFERER']);
}
else {
header('Location: index.php');
}
?>а для изменения лимита может быть вызыван аналигичный скрипт limits.php:
<?
session_start();
require_once ("functions.php");
$params = array('limit');
require_once ("params.php");
if ($limit<-1) $limit=-1;
else if ($limit>100) $limit=100;
$_SESSION['limit']=$limit;
$_SESSION['start']=0; //При изменении лимита начинаем всегда с 0
if (isset ($_SERVER['HTTP_REFERER'])) {
header('Location: '.$_SERVER['HTTP_REFERER']);
}
else {
header('Location: index.php');
}?>Оба последних скрипта используют общий для всего сайта обработчик параметров с именем params.php:
<?
while (list($num,$var) = each($params)) {
if (!empty($_POST[$var])) $$var = trim(htmlspecialchars(magic($_POST[$var])));
else if (!empty($_GET[$var])) $$var = trim(htmlspecialchars(magic($_GET[$var])));
else $$var = '';
}
?>Функция magic, служащая для корректной обработки кавычек, включена в файл функций functions.php:
function magic($path){
if( ini_get('magic_quotes_sybase')=='1'){
$path=str_replace('""','"',$path);
$path=str_replace("''","'",$path);
}
else {
if(@get_magic_quotes_gpc()=='1'){
$path=str_replace('\\"','"',$path);
$path=str_replace("\\'","'",$path);
$path=str_replace("\\\\","\\",$path);
}
}
return $path;
}Описанный пример предполагает, что подключение к базе данных с именем test, находящейся на локальном хосте, описано в файле db.php:
$mysql=mysql_connect("localhost", "root", "root"); //хост, логин, пароль
mysql_select_db("test"); //имя базы данных
и эта база имеет таблицу с именем notes и следующей структурой:
id int PRIMARY KEY auto_increment, date bigint, title varchar(255), rating int, anons text
Файл, позволяющий создать таблицу, находится в архиве под именем !sql!.sql, а подробная инструкция о настройке и выполнении скриптов на локальном сервере под Windows XP доступна в этой статье.
Работающий пример, содержащий все рассмотренные функции и файлы, можно скачать по ссылке ниже. Разумеется, с ним есть смысл работать, когда таблица notes наполнена данными.
После создания таблицы в базе с именем test запрос вносит туда 60 записей.
Скачать пример (7 Кб)
Для небольшого числа статей функция navigation_string выдаст примерно вот такое меню:

Если статей становится много, функция гибко уберет лишние ссылки:


|
|