Скрипт постраничной навигации (расширенная версия)

Author Автор: Роман Чернышов    Опубликовано: 29 марта 2012

Не так давно я опубликовал пост в котором приводил пример скрипта постраничной навигации. Скрипт был предельно прост, выводил ссылки: [В начало, Предыдущая, 1, 2, 3, Следующая, В конец]. Примеров аналогично скрипта старой версии в интернете множество и у всех у них есть один весомый недостаток — навигация выводится в виде трех-пяти ссылок га ближайшие страницы, а что делать если у нас 1000 страниц?

Пример работы скрипта старой версии:

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

Пример работы скрипта новой версии:

Скрипт представляет собой PHP функцию.

function pagenation($page = 1, $num = 10, $di = 10, $link_url = », $DBtable, $DBwhere, $type = 1, $settings)

Параметры функции pagenation();

1. $page — Текущая страница, значение берется из $_REQUEST[‘page’]
2. $num — Количество выводимых записей на страницу
3. $di — Количество страниц отображаемых в навигации, умноженное на два.
4. $link_url — Адрес текущей страницу, будет пожставлен к ссылкам постраничной навигации (вначало)
5. $DBtable — Название таблицы в базе данных, вывод из которой производится
6. $DBwhere — Можно указать условие, по которому будут выводится записи из БД
7. $type — Тип выводимой постраничной навигации, 1 — простая навигация, 2 — навигация + статус (пример: Страница 1 из 15), 3 — навигация + статус + HTML форма, для ввода номера страницы и быстрого перехода на нее
8. $settings — Массив с параметрами подключения к БД
$settings[‘db_host’] = ‘localhost’;
$settings[‘db_name’] = ‘dbname’;
$settings[‘db_user’] = ‘user’;
$settings[‘db_pass’] = ‘pass’;

Пример вызова функции

$pgn = pagenation(@$_REQUEST['page'], 10, 10, '?idpost=1', 'regions', "", 3, $settings);

В этом случае функция вернет следующие значения:
Данная функция возвращает ассоциативный массив, в котором садержаться следующие значение

$pgn[‘start’] — начало выводимых записей из БД
$pgn[‘num’] — количество выводимых записей
$pgn[‘tatal’] — количество страниц
$pgn[‘posts’] — общее количество записей в таблице
$pgn[‘html’] — готовый HTML код постраничной разбивки
$pgn[‘status’] — (если указан $type = 2)содержит информацию(HTML код) о текущей странице и общем количестве страниц (пример: Страница 1 из 15 )
$pgn[‘from’] — (если указан $type = 3) содержит HTML форму, для ввода номера страницы и быстрого перехода на нее

Системные требования скрипта
В скрипте используется библиотека PHP PDO, для работы с базой данный mySQL (библиотека php-pdo_mysq), для его работы требуется версия PHP 5.2 и более. База данный mySQL версии 4 и более.

Привожу полный листинг всего скрипта, вместе с HTML и CSS кодом, думаю при желании вы без особого труда сможете изменить его и интегрировать в свой сайт. Листинг содержит подробные комментарии.

<?php    
error_reporting('E_WARNING');
 
//Настройки подключения к БД
$settings['db_host'] = 'localhost';
$settings['db_name'] = 'dbname';
$settings['db_user'] = 'user';
$settings['db_pass'] = 'pass';
$settings['db_charset'] = 'utf8';
 
/*
* pagenation($page = 1, $num = 10, $di = 10 (диапазон разброса), $link_url = '', $DBtable, $DBwhere, $settings (Параметры подключения к БД))
* type (1 - pagenation, 2 - +status, 3 - +form)
* return = array ('start' => NUM, 'num' => NUM, 'total' => NUM, 'posts' => NUM, 'html' = TEXT, 'status' = TEXT, 'form' = TEXT)
*/
function pagenation($page = 1, $num = 10, $di = 10, $link_url = '', $DBtable, $DBwhere, $type = 1, $settings) {
	if($DBwhere>'')$DBwhere = 'WHERE '.$DBwhere;
	$db = new PDO("mysql:dbname={$settings['db_name']};host={$settings['db_host']}",$settings['db_user'],$settings['db_pass']); // подключаемся к БД
	$sql = "SELECT count(`id`) FROM `$DBtable` $DBwhere";
	$posts = $db->query($sql)->fetchColumn(); // получем значение кол-во всех записей
	$total = intval(($posts - 1) / $num) + 1;  
	$page = intval($page); 
	if(empty($page) or $page < 0) $page = 1; 
	if($page > $total) $page = $total; 
	$start = $page * $num - $num;
	if ($page != 1) 
		$pervpage = "<a href=\"$link_url&page=-1\"><<</a> 
       	        	     <a href=\"$link_url&page=".($page-1)."\"><</a> "; 
	if ($page != $total) 
		$nextpage = "<a href=\"$link_url&page=".($page+1)."\">></a>
			     <a href=\"$link_url&page=$total\">>></a> "; 
	$out='<span>'.$page.'</span>';
	for($i=1;$i<=$di;$i++):
		if($page - $i > 0) $pageL = "<a href=\"$link_url&page=".($page-$i)."\">".($page-$i)."</a> "; else $pageL='';
		if($page + $i <= $total) $pageR = "<a href=\"$link_url&page=".($page+$i)."\">".($page+$i)."</a>"; else $pageR='';
		$out=$pageL.$out.$pageR;
	endfor;
	$out='<div class="pagenation" align="center">'.$pervpage.$out.$nextpage.'</div>';
        if($type>=2)$data['status']="<div class=\"pagenation-info\">Страница $page из $total</div>";
        if($type==3)$data['form']="<form class=\"pagenation-form\" method=\"post\" action=\"$link_url\"><input type=\"text\" name=\"page\" value=\"$page\" class=\"inputbox\"/><input type=\"submit\" value=\">>\"/></form>";
	$data['start']=$start;
	$data['num']=$num;
	$data['total']=$total;
	$data['posts']=$posts;
        $data['html']=$out;
	return $data;
}
 
 
/*
Параметры функции pagenation();
1. $page - Текущая страница, значение берется из $_REQUEST['page']
2. $num - Количество выводимых записей на страницу
3. $di - Количество страниц отображаемых в навигации, умноженное на два.
4. $link_url - Адрес текущей страницу, будет пожставлен к ссылкам постраничной навигации (вначало)
5. $DBtable - Название таблицы в базе данных, вывод из которой производится
6. $DBwhere - Можно указать условие, по которому будут выводится записи из БД
7. $type - Тип выводимой постраничной навигации, 1 - простая навигация, 2 - навигация + статус (пример: Страница 1 из 15), 3 - навигация + статус + HTML форма, для ввода номера страницы и быстрого перехода на нее
8. $settings - Массив с параметрами подключения к БД
	$settings['db_host'] = 'localhost';
	$settings['db_name'] = 'dbname';
	$settings['db_user'] = 'user';
	$settings['db_pass'] = 'pass';
*/
 
$pgn = pagenation($_REQUEST['page'], 10, 10, '?idpost=1', 'table', "", 3, $settings);
 
/*
Данная функция возвращает ассоциативный массив, в котором садержаться следующие значение
$pgn['start'] - начало выводимых записей из БД
$pgn['num'] - количество выводимых записей
$pgn['tatal'] - количество страниц
$pgn['posts'] - общее количество записей в таблице
$pgn['html'] - готовый HTML код постраничной разбивки
$pgn['status'] - (если указан $type = 2)содержит информацию(HTML код) о текущей странице и общем количестве страниц (пример: Страница 1 из 15 )
$pgn['from'] - (если указан $type = 3) содержит HTML форму, для ввода номера страницы и быстрого перехода на нее
*/
 
//получаем записи из БД (начиная с $start, кол-во записей = $num)
 
$db = new PDO("mysql:dbname={$settings['db_name']};host={$settings['db_host']}",$settings['db_user'],$settings['db_pass']);
$db->query ( "SET character_set_connection = '{$settings['db_charset']}';");
$db->query ( "SET character_set_client = '{$settings['db_charset']}';");
$db->query ( "SET character_set_results = '{$settings['db_charset']}';");
$db->query ( "SET NAMES '{$settings['db_charset']}';");
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); // Коннектимся с базой и устанавливаем кодировку. 
$sql = "SELECT * FROM `table` LIMIT {$pgn['start']}, {$pgn['num']}"; 
$allposts = $db->query($sql)->fetchAll(); // получем список записей которые будем выводить на данной странице
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<style>
#contener {margin:20px auto;width:500px;position:relative;}

.pagenation {color: #636363;border: 0px;font-family: tahoma;margin:10px 0}
.pagenation a:link,.pagenation a:visited,.pagenation a:active {display: inside;text-decoration: none;color: #FFF;background-color: #13739B;border: 1px solid #e1e1e3;padding: 3px 6px;font-size: 11px}
.pagenation a:hover {background-color: #24323B;color: #ffffff;border-color: #e1e1e3;}
.pagenation span {text-decoration: none;background-color: #24323B;padding: 3px 6px;border: 1px solid #e1e1e3;color: #fff;font-size: 11px;}
.pagenation span.nav_ext {border: none;background: transparent;}
.pagenation-form .inputbox {width:40px;border:1px solid #eee;}
</style>
 
</head>
<body>
<div id="contener">
<!-- Выводим список записей, ID записи и название-->
<?foreach($allposts as $item):?>
	<?=$item['id']?>. <?=$item['name']?><br/>
<?endforeach?>
 
<?php
// если страниц больше чем одна, выводим постраничную навигацию
if ($pgn['total']>1) echo $pgn['html'].$pgn['status'].$pgn['form'];
?>
</div>
</body>
</html>

Надеюсь данный скрипт будет вам полезен. так же вы можете скачать его исходник и посмотреть живой пример работы (вывод списка регионов).

13 комментариев to “Скрипт постраничной навигации (расширенная версия)”

  • Александр 06.04.2012 в 10:12 пп

    спасибо)))ваш блог просто находка для моего сайта,все что нужно для меня прям))кстати обзор скрипа комментирования начал писать)вы молодец,таких людей очень мало к сожалению((

  • joseph 05.07.2012 в 11:54 дп

    не могу разобраться( и пример не работает
    я в вашем исходнике меняю параметры подключения к базе, ставлю в вызове функции свою таблицу — но без результатно — не работает, что я делаю не так? или что я упускаю? в общем как запустить?)

    • Роман Чернышов 05.07.2012 в 12:09 пп

      Возможно, что-то делаете не так. скинте мне ваш код в обратную связь, я попробую разобраться где допущена ошибка.

  • joseph 05.07.2012 в 1:14 пп

    а вот, уже разобрался!) Ошибка в моих руках, — не от туда… Спасибо за код (он у вас качественный) и оперативность! И вообще за Ваш замечательный сайт!

  • имя 08.08.2012 в 5:42 пп

    !!!! Это конечно всё хорошо, НО 150 строчек кода обработка на сервере а чего добились?
    по сути идеальный вариант — всегда видим номера первой и последней страницы какие то промежуточные и !!! внимание фишка — на javascript либо css реализовывается вывод всего количества страниц в дополнительную область либо всплывающей подсказкой . В рамках 200 страниц это боле чем лучшее решение. а пхп в штатном режиме уже всё обработает.

    • Роман Чернышов 08.08.2012 в 6:00 пп

      Да вполне с вами согласен, данный пример всего скорее носит ознакомительный характер или вариант для небольшого кол-ва страниц. В будущем возможно будет реализован более продвинутый скрипт со всеми вами описанными возможностями.

  • Александр 03.12.2016 в 6:29 пп

    Сделал с вашей пагинацией то что не мог сделать с другими. А именно, соединение нескольких таблиц из базы, чтобы не создавать для каждой категории(таблицы) отдельных файлов. Теперь, записи выводятся в зависимости от запрашиваемой категории(выбираем нужную таблицу через UNION и выводим ее содержимое).

    Но, есть одна проблема, которая портит все это дело. В борьбе с этой проблемой и прошу помощи. А проблема в следующем: Строки для пагинации просчитываются лишь по первой таблице, из всех таблиц которые прописываются через UNION. И независимо от того сколько строк в других таблицах, количество страниц отображается в постраничной навигации лишь из того расчета, сколько строк в первой по счету таблице.

    Как сделать так, чтобы количество выводимых страниц просчитывалось в зависимости от того, сколько строк в таблице, которую в данный момент мы подставили под вывод?

    Если нужно, могу выложить свой код.

    • Роман Чернышов 04.12.2016 в 12:32 пп

      А при определении общего числа строк в базе данных, в переменной $posts, в запросе используется UNION? Да, можете выслать код, посмотрим на примере.

  • Александр 06.12.2016 в 10:09 пп

    Пытаюсь в который раз здесь показать код, но страница обновляется, и не сообщения, ни любого оповещения о том, отправилось ли куда, или если нет, то почему…

  • Александр 06.12.2016 в 10:14 пп

    Может скрипт комментариев блокирует сообщения с кодом? Или как длинный текст не проходит?

  • Anastasia 07.07.2020 в 3:11 пп

    Подскажите, как Ваш скрипт соединить со стандартным скриптом opencart 3?

    class Pagination {
    public $total = 0;
    public $page = 1;
    public $limit = 10;
    public $num_links = 10;
    public $url = »;
    public $text_first = ‘|<‘;
    public $text_last = ‘>|’;
    public $text_next = ‘>’;
    public $text_prev = ‘<‘;

    /**
    *
    *
    * @return text
    */
    public function render() {
    $total = $this->total;

    if ($this->page page;
    }

    if (!(int)$this->limit) {
    $limit = 10;
    } else {
    $limit = $this->limit;
    }

    $num_links = $this->num_links;
    $num_pages = ceil($total / $limit);

    $this->url = str_replace(‘%7Bpage%7D’, ‘{page}’, $this->url);

    $output = »;

    if ($page > 1) {
    $output .= ‘url) . ‘»>’ . $this->text_first . ‘‘;

    if ($page — 1 === 1) {
    $output .= ‘url) . ‘»>’ . $this->text_prev . ‘‘;
    } else {
    $output .= ‘url) . ‘»>’ . $this->text_prev . ‘‘;
    }
    }

    if ($num_pages > 1) {
    if ($num_pages <= $num_links) {
    $start = 1;
    $end = $num_pages;
    } else {
    $start = $page — floor($num_links / 2);
    $end = $page + floor($num_links / 2);

    if ($start $num_pages) {
    $start -= ($end — $num_pages);
    $end = $num_pages;
    }
    }

    for ($i = $start; $i <= $end; $i++) {
    if ($page == $i) {
    $output .= '’ . $i . »;
    } else {
    if ($i === 1) {
    $output .= ‘url) . ‘»>’ . $i . ‘‘;
    } else {
    $output .= ‘url) . ‘»>’ . $i . ‘‘;
    }
    }
    }
    }

    if ($page < $num_pages) {
    $output .= 'url) . ‘»>’ . $this->text_next . ‘‘;
    $output .= ‘url) . ‘»>’ . $this->text_last . ‘‘;
    }

    $output .= »;

    if ($num_pages > 1) {
    return $output;
    } else {
    return »;
    }
    }
    }

  • ТОМ 26.11.2021 в 5:59 пп

    Подскажите, пожалуйста, как прикрепить возможность вывода по категориям, если в таблице их несколько?
    Отредактировал выборку так: $sql = «SELECT * FROM `table` WHERE cat=’$cat’ ORDER BY id LIMIT {$pgn[‘start’]}, {$pgn[‘num’]}»;
    Результат: На страницах выводятся посты только по определенной категории, но количество страниц не сокращается.

    Если у меня в одной из категории 30 постов, а в общей таблице 99постов, и выводится по 10 постов на странице, то как с исходником, так и с моими изменениями, все-равно делится на 10 страниц.

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

    Как мне обрезать пустые страницы?.Чтобы количество страниц просчитывалось не от общего числа постов в таблице, а от общего количества постов в категории?

    • Роман Чернышов 27.11.2021 в 1:44 дп

      В функции pagenation, есть запрос к БД:
      $sql = «SELECT count(`id`) FROM `$DBtable` $DBwhere»;
      который как раз получат кол-во всех записей в БД, и на основе этого значения рассчитывает кол-во страниц.

      Вызовете функцию вот так(указав в шестом параметре условия, а именно категорию):

      $pgn = pagenation($_REQUEST[‘page’], 10, 10, ‘?idpost=1’, ‘table’, «cat=’$cat’», 3, $settings);

Оставить комментарий

Автор блога
Роман Чернышов
Веб-разработчик,
Full Stack
Senior, Architect
PHP, JavaScript, Node.JS, Python, HTML 5, CSS 3, MySQL, Bash, Linux Admin
Заказать работу
предложить оффер

Моя книга
Книга. Веб-разработчик. Легкий вход в профессию
Печатная книга
Веб-разработчик.
Легкий вход в профессию
Оформить предзаказ
Последние вопросы
Список вопросов
Последние комментарии
Меню

Archive

Мои проекты
Insurance CMS Love Crm CMS Совместные покупки Мой PHP Framework Хостинг для моих клиентов Лицензии на мой софт и поддержка