Итак, вы много раз видели, как дынные выводятся постранично и вы всегда хотели сделать так на своем сайте. Сегодня я расскажу как сделать постраничный вывод из MySQL.
Для начала немного теории. Что надо сделать? Сначала, надо проверить выбрана ли страница просмотра. Потом надо подсчитать откуда выводить записи. Делается это просто: текущую страницу умножаем на количество записей на страницу. Наконец, надо сделать SQL-запрос к базе данных и вывести результат. И в конце концов написать нивигацию.
Приступим. Выполните SQL-запрос:
CREATE TABLE tbl_books (book_id int(11) NOT NULL auto_increment, book_name varchar(50) NOT NULL default "", book_cash float NOT NULL default "0", PRIMARY KEY (book_id)) TYPE=MyISAM; INSERT INTO tbl_books VALUES (1, "Книга номер 1", "2"); INSERT INTO tbl_books VALUES (2, "Книга номер 2", "3"); INSERT INTO tbl_books VALUES (3, "Книга номер 3", "4"); INSERT INTO tbl_books VALUES (4, "Книга номер 4", "5"); INSERT INTO tbl_books VALUES (5, "Книга номер 5", "6"); INSERT INTO tbl_books VALUES (6, "Книга номер 6", "7"); INSERT INTO tbl_books VALUES (7, "Книга номер 7", "8"); INSERT INTO tbl_books VALUES (8, "Книга номер 8", "9"); INSERT INTO tbl_books VALUES (9, "Книга номер 9", "10"); INSERT INTO tbl_books VALUES (10, "Книга номер 10", "11"); INSERT INTO tbl_books VALUES (11, "Книга номер 11", "12"); INSERT INTO tbl_books VALUES (12, "Книга номер 12", "13"); INSERT INTO tbl_books VALUES (13, "Книга номер 13", "14"); INSERT INTO tbl_books VALUES (14, "Книга номер 14", "15"); INSERT INTO tbl_books VALUES (15, "Книга номер 15", "16");
Я предлагаю все оформить в виде функций обработчиков. Создадим функцию page(), которая обрабатывает данные о запрошенном номере страницы:
Что она делает? Проверяет выбрана ли страница и если в ней присутствуют буквы, то выводит сообщение об ошибке. Далее сделаем SQL-запрос:
function sql_query($onpage, $page, $table) { $begin = $page*$onpage; // откуда начинать $sql = "SELECT * FROM ".$table." LIMIT ".$begin.", ".$onpage; $result = mysql_query($sql) or die(mysql_error()); return $result; }
Функция навигации:
function navigation($onpage, $page, $table)
{
$return = null;
$count = mysql_query("SELECT COUNT(*) FROM tbl_books") or die(mysql_error());
$count = mysql_fetch_array($count);
$count = $count;
$pages = $count/$onpage;
if($page!==0){
$prev = "<";
} else {
$prev = "<";
}
if($page
С функциями покончили! Как ими пользоваться?
$onpage = 4; // записей на страницу
$table = "tbl_books"; // из какой таблицы
mysql_connect("localhost", "root", "pass") or die(mysql_error()); // коннект к БД
mysql_select_db("test"); // выбор БД
$page = page(); // определяем страницу
$result = sql_query($onpage, $page, $table); // sql - запрос
while($data = mysql_fetch_array($result)) // цикл вывода
{
// шаблон вывода нужно изменить
// $data["название_поля"] - содержание поля
echo $data["book_id"]." ".$data["book_name"]."
";
echo $data["book_cash"]."$
"; } $navigation = navigation($onpage, $page, $table); // определим навигацию echo $navigation; // выведем ее mysql_close(); // отключение от БД?>
Хорошо Плохо
Что такое разбивка на страницы? Самый простой пример - поисковые машины. Вы даете команду на поиск в ответ на что сервер выдает тысячи ссылок (и прочая информация…
Регулярно в форуме задают один и тот же вопрос: как сделать постраничный вывод. И каждый раз человеку отвечают: "Легко! m строк, начиная с n-ной: Select запрос Limit $n,$m". На самом деле не так всё просто.
Я уже писал про синтаксис параметра LIMIT, однако, без толку. Для полноценного постраничного вывода строк из базы требуется большее. Требуется
- Обработать номер страницы (в том числе проверить, не больше ли он общего количества страниц)
- Нарисовать навигационную строку (чтобы не просто "вперед-назад", а с ссылками на несколько соседних страниц)
Тут-то и начинаются главные проблемы.
Недавно я работал над сайтом, в котором эти постраничные выводы в статистике были в каждом списке (а списков было много!). Тут-то и созрело решение, как свести все эти штучки к простому и единому решению. Получились четыре функции, которые я теперь использую везде, где нужен постраничный вывод данных, и не напрягаю попусту голову проблемой (как же я делал это там, как бы вынуть этот код оттуда?).
Первая функция — для внутреннего пользования двумя следующими. Берёт номер страницы, общее количество строк и количество строк на странице и выдаёт номер страницы, уже проверенный. Вторая берёт то же самое, проверяет номер страницы и выдаёт парамерт LIMIT либо полный (LIMIT n,m), либо краткий (LIMIT m), если это первая страница, либо ничего не выдаёт. Третья функция из тех же трёх параметров и адреса для ссылки делает навигационную строку. Ещё одна функция выдаёт число для нумерованного списка.
Этого достаточно для нормальной работы с постраничным выводом данных. Посмотрим, что получается в коде программы:
// кол-во строк в страницах
$in_page
=
10
; // получаем количество строк
$amount
= @
mysql_result
(mysql_query
("SELECT count(id) as goods_total FROM goods"
),
0
); // рисуем навигационную строку и пишем начало таблицы Print("
"goods.php?page="
)
b
>.
" // формируем запрос к базе
$goods_result
=
mysql_query
("SELECT id, name, description, price FROM goods ORDER BY name, price "
. <
b
>
get_limit
($page
,
$amount
,
$in_page
)
b
>); // получаем номер для нумерованного списка
$count
= <
b
>
get_count_limit
($page
,
$amount
,
$in_page
)
b
>;
// выводим строки While ($good_row
=
mysql_fetch_array
($goods_result
)) {
$count
++; Print (" // фон каждой второй строки — серым цветом If ($count
/
2
==
intval
($count
/
2
)) Print (" bgcolor=#e1e1e1"
); Print ("> // конец таблицы и нижняя навигационная строка Print("
$in_page
,
"goods.php?page="
)
b
>.
""
);
\n"
);$count. ${good_row}
${good_row}${good_row}
Это ВСЁ, что нужно для постраничного вывода! Больше напрягаться не надо!
Одно только пояснение — в качестве параметра функции draw_bar указывается адрес этого скрипта со всеми параметрами так, чтобы он туда только дописывал номер страницы. Если сложная выборка, надо будет ручками формировать этот адрес (всё-таки упрощение жизни вышло относительное: упрощаем одно — усложняем другое).
Делаем постраничный вывод на Php + Mysql
В самом начале своего пути веб-программиста знаний у меня как и все было еще очень мало, но желания хоть отбавляй. И вот я начал писать свой первый скрипт - гостевую книгу. В то время интернет только начал зарождаться и гостевая книга была популярна. Но после нескольких дней я столкнулся с проблемой, которую в то время не мог решить: как выводить все сообщения по 10 на странице? С этим было просто, но вот как сделать ссылки на страницы, при переходе на которые показывались бы следующие 10 страниц???
Это было для меня огромной проблемой и для ее решения я оббегал кучу форумов и сайтов. Постраничный вывод очень нужен и в наше время, но статей по нему до сих пор почти нет. Я решил исправить эту несправедливость. На своем примере я покажу вам постраничный вывод сообщений из mysql-базы, т.к. сейчас она очень популярна и имеет множество преимуществ по сравнению с файлами. Если вам будет нужно, то я могу показать вам постраничный вывод сообщений из файла.
Сначала надо пределить с базой, в которой хранятся наши сообщения. Не будем
придумывать огромные базы с сотнями таблиц. Возьмем для примера такую базу, в
которой только только 1 таблица и в ней 2 поля: номер сообщения и само
сообщение. Чуть ниже вы можете посмотреть на структуру таблицы из этой базы.
id | text |
1 | text1 |
2 | text2 |
3 | text3 |
4 | text4 |
5 | text5 |
С базой определились, можно начинать скрипт. Для начала подключимся к нашей новоиспеченной базе и вычислим число строк в таблице posts.
$link = mysql_connect("localhost","user","pass"); //Подключаемся к серверу базы данных
mysql_select _db("base",$link); //Выбираем базу
$posts = mysql_query("select * from posts");
$total_posts = mysql_num_rows($posts); //Считаем число строк в таблице с сообщениями (posts)
Итак, начало положено. Теперь будем писать функцию для отображения ссылок на другие страницы с сообщениями, собственно говоря сам постраничный вывод. Это не слишком сложная функция, но и не самая простая, т.к. меньше она быть не должна, а больше по вашему усмотрению. Мы задаем функции 4 аргумента (в комментарии они описаны). Вы можете добавить несколько примочек в эту функцию на свой вкус я дал вам лишь основу, дальше двигайтесь сами. Можно например выделить ссылку на текущую страничку.
function
print_links($total,$page,$number,$links) //1 аргумент - всего
сообщений, 2 - номер текущей страницы, 3 - число сообщений на странице, 4 -
число отображаемых ссылок
{
$return = null;
$pages = ceil($total/$number); //Вычисляем сколько должно получиться страниц
if
($page+$links <= $pages)
{
$start = $page;
}
else
{
$start = $pages-($links-1);
$finish = $pages;
}
if
($start < 0)
{
$start = 1;
}
for
($i=$start;$i<=$finish;$i++) //Записываем в переменную ссылки
{
$return .= " ".$i." ";
}
return $return; }
Итак, функция у нас готова. В ней вы можете указать сколько ссылок будет отображаться и сколько сообщений выводить. Осталось самое легкое: надо вывести сообщения в браузер, с учетом номера страницы, на которой сейчас посетитель.
Для начала добавим небольшую проверку. Если у вас не указан номер страницы, то по умолчанию вам будет отображаться первая страница. МОжно добавить также дополнительные проверки, чтобы исключить работу скрипта при запросах вида: $#$## или фав1324. Это повысит безопасность скрипта, а следовательно и сайта.
if
(!isset($page)) { $page = "1"; } //Здесь мы делаем проверку. Если
переменная page (номер страницы) не указана, то ей присваивается значение 1
print print_links($total_posts,$page,"10","5"); //Выводим в браузер ссылки
$query = mysql_query("select
* from posts limit ".(($page-1)*10).",10 ");
//Выбираем нужное число сообщений
while
($row=mysql_fetch_array($guest)) { print "
".$row["text"]."
";
//Выводим сообщения (дизайн делайте сами) }
mysql_close($link);
?>
Вот теперь все. Я показал вам все функции: для генерации ссылок, для вывода
сообщений, для подключения к базе, остальное в вашим руках. Если вам интересно
будет как сделать постраничный вывод на файлах, то пишите мне и я напишу статью,
чтобы всем было понятно.
Если что-то непонятно, то заходите ко мне на сайт или пишите мне на email
Половина второго ночи, несколько дней недосыпа... И вдруг озарение - наконец-то я понял, какой-такой супер-пупер скрипт мне нужен для раскрутки моего нового сайта. Сказано - сделано, сажусь... нет не писать этот супер-пупер скрипт:) Программисты народ ленивый, спецы по раскрутке тем более (отсюда и баннерообменные сети, авторегистраторы в каталогах и пр. лентяйские штучки). В общем лезу на Google и начинаю методично обшаривать Рунет в поисках требуемого. Проходит час, два... В душу закрадываются смутные подозрения, плавно перерастающие в уверенность, что требуемый мне скрипт в природе либо не существует, либо спрятан на чьем-то заповедном локалхосте с правами доступа 000.
Разбиваю стоящую перед скриптом задачу на несколько составных и минут за 15 пишу реализацию большинства его (скрипта) функций:) Радостно берусь за следующую фичу... В общем, необходимо всего-то навсего обеспечить постраничный вывод контента. То есть, например, имеется 60 статей и нужно эти статьи выводить по 10 на страницу и построить меню для оного вывода в виде "1 2 3 ..."
Четыре утра, окромя заветного "LIMIT" в голову ничего не
приходит. И дело даже не в том, что БД к моему скрипту
никакого отношения не имеет. С горечью понимаю, что
квалификация потеряна, лучшие годы жизни прожиты впустую и...
иду на Google ;)
После... в общем уже наступил рассвет. К
этому времени я познакомился с кучей литературы по данному
вопросу, но везде ситуация так или иначе рассматривалась в
контексте работы с SQL, либо я постоянно наталкивался на
какую-то растиражированно-заумную статью про "отделение
алгоритма постраничного вывода от контекста
или-что-то-в-этом-роде" (ИМХО, нижеприведенные 7 строчек кода
эту проблему решают) в которой ничегошеньки не понял... :(И
вот когда я уже отчаялся и решил что утро вечера мудренее, на
каком-то дремучем, заросшим мхом форуме (адрес к сожалению
канул в Лету - по крайней мере у меня его нет), наткнулся на
переписку некоего вечно извиняюшегося Программера и безумного
и злобного Модератора - тема переписки была посвящена именно
построению меню для постраничного вывода. И это было именно то
что нужно!
В общем, ниже по тексту я исправляю несправедливость: теперь в Интернете есть статья о том, как обеспечить построение меню для постраничного вывода! Простой рабочий код на PHP, с подробными комментариями. Никакой излишней функциональности типа ссылок "next page". Сделано сие намеренно - ни разу в жизни не нажимал на "next" если можно было нажать на номер страницы - а данная статья написана с целью дать возможность понять основной принцип, т.е. чем меньше кода, тем лучше (хотя кнопка "next" и добавляется тремя строками кода).
Соглашения о комментариях к коду:
- "Статья" - это некий целостный блок данных (не обязательно текстовых) который и выводится по несколько штук на страницу (это могут быть статьи, новости, картинки и пр.)
- "Страница" - это страница:) на которой расположено некоторое количество "статей".
Таким образом, на экране браузера мы получили что-то вроде "1 2 3 4 5 6 7 8", при этом URL (на моем компьютере, при выбранной третьей "странице") выглядит так: http://localhost/ep/ep.php?from=20 . Обратите внимание, на то, что странице под номером "3" соответствует значение from=20 то есть отсчет выводимых статей будет вестись в данном случае с 20-й.
Вообще, как вы уже поняли, переменная $from играет здесь ключевую роль. Она участвует в построении ссылок на каждую отдельную страницу (если, конечно, можно так выразиться:), и самое главное - дает нам точку отсчета для вывода статей. Например (и наверняка вы сделаете именно так) указатели на статьи (или сами статьи;) можно поместить в массив, с последующей выборкой и выводом в браузер по 10 статей, начиная от значения $from.
То есть еще раз иными словами: весь огород собственно и городился ради того, чтобы дать скрипту данные относительно того на какой "странице" сейчас находится посетитель и начиная с какого номера "статьи" следует вывести заданное количество этих статей на страницу - а это и есть значение переменной $from. Т.е. при $from=20 выведутся страницы с 21 по 30 (это также зависит от реализации вывода и значения переменной $articles_per_page)