Постраничный вывод из MySQL

Как сделать постраничный вывод из MySQL: по 10 (20, 30) записей на страницу, а внизу - ссылки на остальные страницы?

Чтобы получить нужные записи, воспользуемся оператором LIMIT, который вызывается с двумя параметрами - с какой записи начинать, и сколько выводить:

SELECT id, title FROM items LIMIT 0, 10;

Этот запрос вернет записи с первой по 10, поскольку нумерация начинается с 0. Cоответственно, запросы для второй и третьей страницы будут выглядеть

SELECT id, title FROM items LIMIT 10, 10;
SELECT id, title FROM items LIMIT 20, 10;

Как видите, нам надо лишь передать в скрипт число, которое потом подставить в запрос.

Для построения постраничной навигации нам еще понадобится общее число записей в таблице. Это можно сделать с помощью запроса

SELECT COUNT(*) FROM items;
$query = "SELECT COUNT(*) FROM items";
$res = mysql_query( $query );
$total = mysql_result( $res, 0, 0 );

Далее определим, сколько всего получится страниц:

$cnt_pages = ceil( $total / ITEMS_PER_PAGE );

Здесь используется константа ITEMS_PER_PAGE, в которой хранится количество выводимых на странице записей.

<?php
$dblocation = "localhost";   // Имя сервера
$dbuser     = "root";        // Имя пользователя
$dbpswrd    = "";            // Пароль
$dbname     = "catalog";     // Имя базы данных

DEFINE('ITEMS_PER_PAGE', 5);

// Соединение с сервером базы данных
$dblink = mysql_connect( $dblocation, $dbuser, $dbpswrd );
mysql_query( 'SET NAMES cp1251' );
// Выбираем базу данных
mysql_select_db( $dbname, $dblink );

// Выбираем из БД общее количество записей
$query = "SELECT COUNT(*) FROM products WHERE 1";
$res = mysql_query( $query );
$total = mysql_result( $res, 0, 0 );
   
// Проверяем передан ли номер текущей страницы
if ( isset($_GET['page']) ) {
  $page = (int)$_GET['page'];
  if ( $page < 1 ) $page = 1;
} else {
  $page = 1;
}

// Сколько всего получится страниц
$cnt_pages = ceil( $total / ITEMS_PER_PAGE );
if ( $page > $cnt_pages ) $page = $cnt_pages;
// Начальная позиция
$start = ( $page - 1 ) * ITEMS_PER_PAGE;

$query = "SELECT id, title, price
          FROM products
          ORDER BY price ASC
          LIMIT "
.$start.", ".ITEMS_PER_PAGE;
$res = mysql_query( $query );

// Выводим "шапку" таблицы
echo '<table border="1" cellpadding="5" cellspacing="0">';
echo '<tr>';
echo '<th>ID</th>';
echo '<th>Наименование</th>';
echo '<th>Цена</th>';
echo '</tr>';

while( $prd = mysql_fetch_array( $res ) )
{
    echo '<tr>';
    echo '<td>'.$prd['id'].'</td>';
    echo '<td>'.$prd['title'].'</td>';
    echo '<td>'.$prd['price'].'</td>';   
    echo '</tr>';
}

echo '</table>';

// Строим постраничную навигацию
if ( $cnt_pages > 1 )
{
    echo '<div style="margin:1em 0">&nbsp;Страницы: ';
    // Проверяем нужна ли стрелка "В начало"
    if ( $page > 3 )
        $startpage = '<a href="'.$_SERVER['PHP_SELF'].'?page=1"><<</a> ... ';
    else
        $startpage = '';
    // Проверяем нужна ли стрелка "В конец"
    if ( $page < ($cnt_pages - 2) )
        $endpage = ' ... <a href="'.$_SERVER['PHP_SELF'].'?page='.$cnt_pages.'">>></a>';
    else
        $endpage = '';

    // Находим две ближайшие станицы с обоих краев, если они есть
    if ( $page - 2 > 0 )
        $page2left = ' <a href="'.$_SERVER['PHP_SELF'].'?page='.($page - 2).'">'.($page - 2).'</a> | ';
    else
        $page2left = '';
    if ( $page - 1 > 0 )
        $page1left = ' <a href="'.$_SERVER['PHP_SELF'].'?page='.($page - 1).'">'.($page - 1).'</a> | ';
    else
        $page1left = '';
    if ( $page + 2 <= $cnt_pages )
        $page2right = ' | <a href="'.$_SERVER['PHP_SELF'].'?page='.($page + 2).'">'.($page + 2).'</a>';
    else
        $page2right = '';
    if ( $page + 1 <= $cnt_pages )
        $page1right = ' | <a href="'.$_SERVER['PHP_SELF'].'?page='.($page + 1).'">'.($page + 1).'</a>';
    else
        $page1right = '';

    // Выводим меню
    echo $startpage.$page2left.$page1left.'<strong>'.$page.'</strong>'.$page1right.$page2right.$endpage;

    echo '</div>';
}
?>

Тут есть проблема, о которой стоит упомянуть: кроме переменной $page нашему скрипту могут быть переданы и другие переменные. Решается это просто:

$uri = strtok($_SERVER['REQUEST_URI'],"?")."?";
if (count($_GET)) {
  foreach ($_GET as $k => $v) {
    if ($k != "page") $uri.=urlencode($k)."=".urlencode($v)."&";
  }
}

и полученную переменную $uri подставляем в код вместо $_SERVER['PHP_SELF']

Комментариев: 17

  1. haZe:

    Что-то не пойму… то есть скрипт великолепный! Спасибо большое, но я что-то не пойму, как развернуть выборку, т.е. не:
    1.2.3.4, а:
    4.3.2.1.
    Буду признателен за совет!

  2. admin:

    haZe мне кажется, что вопрос сформулирован не очень правильно. Может быть, есть необходимость выводить записи (например, новостей) в обратном порядке? Т.е. сначала более свежие записи, а потом более старые? Тогда надо просто изменить запрос к базе данных

    $query = "SELECT id, title, puttime
              FROM news
              ORDER BY puttime DESC
              LIMIT "
    .$start.", ".ITEMS_PER_PAGE;
    $res = mysql_query( $query );

    Если все-таки надо изменить нумерацию страниц, то обрати внимание на строку

    echo $startpage.$page2left.$page1left.'<strong>'.$page.'</strong>'.$page1right.$page2right.$endpage;

    Нам никто не мешает ее “развернуть”

    echo $endpage.$page2right.$page1right.'<strong>'.$page.'</strong>'.$page1left.$page2left.$startpage;
  3. haZe:

    Да, Вы правы, более свежие наверх!
    Спасибо!

  4. Аня:

    НЕ получается ничего(((

  5. admin:

    Аня, не слишком информативный комментарий. Вы не находите? Что не получается? Печатать на компьютере не умеете? Не получается установить Apache+PHP+MySQL? Не выполняется запрос к БД? Что-то еще?

  6. Аня:

    Сделала по-чайниковски - скопировала и заменила на свои данные, но страница даже не загружается. Не пойму, где ошибка.

  7. admin:

    Аня, это пустой разговор. “Не получается” - вообще ни о чем не говорит. Какой у Вас уровень знаний? Apache утсанавливать умеете? Что такое PHP знаете? Выполнить запрос через phpMyAdmin умеете? Чем Вам промочь? Выразить сочувствие? Ну, считайте что выразил.

    Идёте на форум, выкладываете не работающий скрипт, дамп базы данных, объясняете, что не работает - тогда это будет предметный разговор.

  8. Аня:

    Получилось!!!! Вся проблема была в точке тут: echo ”.$prd['id'].”.; Теперь спасибо за скрипт!!))

  9. Аня:

    так что это не у меня ошибка…не ругайтесь уж так на меня))

  10. admin:

    Позвольте вопрос? Ошибка не у Вас. А у кого?

  11. Аня:

    У Вас в скрипте лишняя точка, на которую я не сразу обратила внимание:
    В разделе “Выводим “шапку” таблицы” в while в строке вывода ID после закрывающего тега </td> стоит лишняя точка.

  12. admin:

    Все, теперь понял. Спасибо, исправил :)

  13. Сергей:

    Хороший скрипт, спасибо.
    Есть одна проблема.
    Меняю $_SERVER['PHP_SELF'] на $uri и скрипт не работает.
    Получаю только 1-ю страницу, при клике на другие опять 1-я.
    Подскажите начинающему

  14. admin:

    Сергей, выкладывайте свой код на форуме, посмотрим, в чем там проблема.

  15. El_Kriton:

    С этим кодом все понятно..поставил, работает..спасибо!
    А как сделать, чтобы выводились все номера страниц без “…” и чтобы номер открытой страницы не был ссылкой?
    заранее спасибо

  16. Сергей 2:

    У меня та же проблема, что и у предыдущего Сергея.
    “..и полученную переменную $uri подставляем в код вместо $_SERVER['PHP_SELF']..” - этого мало, нужно ещё знаки вопроса постирать из

    ...
    $page1right = ' | <a href="'.$_SERVER['PHP_SELF'].'?page='.($page + 1).'">'.($page + 1).'</a>';
    ...
  17. Stas:

    Отличный код, хоть и старая разработка, но изменил вывод, немного поддизайнил и все норм работает.

Оставьте свой отзыв