- Нумерация страниц на php (пагинация).
- Другие посты
- Постраничная навигация php: простой скрипт
- ".$myrow['title']."
- Разбиваем страницы на нужное количество
- Определяем страницу, на которой находимся
- Формируем постраничную навигацию
- Постраничная навигация на PHP
- Пример HTML кода
- Логика построения
- Редиректы
- PHP код и его использование
Нумерация страниц на php (пагинация).
Для создания нумерации страниц в готовых CMS рядовым пользователям не нужно задумываться о том, как этот механизм будет функционировать. Большое количество программистов уже позаботились о том, чтобы все выводилось там, где нужно и как нужно. Однако, иногда возникают ситуации, когда в процессе создания собственного шаблона для сайта приходится решать подобные задачи самостоятельно (в особенности, когда готовые решения в виде плагинов не подходят). Здесь нам на помощь приходит php. Далее рассматривается один из примеров подобного скрипта.
Скрипт состоит из функции, которой передаются «входные» параметры. Перед ее вызовом ваш сценарий должен определить все эти необходимые переменные. Для определения номера текущей страницы вы можете «выудить» необходимую информацию, например, из урла (решение данной задачи – ваше домашнее задание).
Итак, определяем все необходимые переменные.
$all = 150; //количество постов в категории (определяем количество постов в базе данных) $lim = 10; //количество постов, размещаемых на одной странице $prev = 3; //количество отображаемых ссылок до и после номера текущей страницы $curr_link = 18; //номер текущей страницы (получаем из URL) $curr_css = "current"; //css-стиль для ссылки на "текущую (активную)" страницу $link = "http://site.ru/category/news/"; //часть адреса, который будет использован для формирования линков на другие страницы
В нужном нам месте вызываем функцию для создания нумерации, передавая ей исходные данные:
pagination($all,$lim,$prev,$curr_link,$curr_css,$link);
Ну и собственно, сама функция. С виду кажется несколько сложно для восприятия, так как идет рутинный и дотошный процесс создания линка по частям. Здесь нужно обратить внимание на три момента:
1. Функция позволяет задавать необходимое количество отображаемых номеров на странице. Если страниц очень много, а вы задали к примеру 3 линка до и после номера текущей страницы, то она сформирует такой результат:
1…14 15 17 18 19 20 21 … 100
2. Можно задать, чтобы при текущей странице до 7 или 10 символы «…» не появлялись, а отображались все страницы до текущей. Подправить это можно в строке 11 (замените 6 любым другим числом страниц).
3. Чтобы исключить дублирование первой страницы для ее линка не добавляются дополнительные данные (?page=1). Соответственно, ваш контроллер должен делать проверку: если параметр page в линке отсутствует, то это первая страница.
Данный скрипт позволяет получать УРЛы с номерами страниц, например, так http://site.ru/category/news/?page=6.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
function pagination($all, $lim, $prev, $curr_link ,$curr_css, $link) < //осуществляем проверку, чтобы выводимые первая и последняя страницы // не вышли за границы нумерации $first=$curr_link-$prev; if($first<1) $first=1; $last=$curr_link+$prev; if($last>ceil($all/$lim))$last=ceil($all/$lim); //начало вывода нумерации //выводим первую страницу $y=1; if($first>1) echo "?page='>1 "; //если текущая страница далеко от 1-й, то часть предыдущих страниц //скрываем троеточием $y=$first-1; if($first>6) < echo "?page='>. "; >else < //если текущая страница имеет номер до 10, то выводим все номера //перед заданным диапазоном без скрытия for($i=2;$i<$first;$i++)< echo "?page='>$i "; > > //отображаем заданный диапазон: текущая страница +-$prev for($i=$first;$i <$last+1;$i++)< if($i==$curr_link)>//если выводится текущая страница, то ей назначается особый стиль css else< $alink = ""; if($i != 1) $alink .= "?page="; $alink .= "'>$i "; echo $alink; > > $y=$last+1; //часть страниц скрываем троеточием if($last2) echo "?page='>. "; //выводим последнюю страницу $e=ceil($all/$lim); if($last $e"; >
Другие посты
Постраничная навигация php: простой скрипт
С проблемой создания постраничной навигации на языке php сталкиваются многие новички-программисты и не все понимают, как она должна работать. Рассмотрим подробно и по пунктам, как создать самую простую пагинацию.
Для начала представим, что у нас уже есть запрос, который в нужном формате выводит все записи из нужной таблицы.
// Подключение к бд $db = mysql_connect("localhost","root",""); mysql_select_db("phpsite",$db); // Вывод записей из таблицы $result = mysql_query("SELECT * FROM `lessons`", $db); $myrow = mysql_fetch_array($result); do< echo "".$myrow['title']."
"; echo "".$myrow['text']."
"; > while ($myrow = mysql_fetch_array($result));
Разбиваем страницы на нужное количество
Мы получили все записи на странице, но теперь их нужно разбивать. Для разбития на страницы мы добавим в наш запрос — вывод определённого количества записей, с помощью «LIMIT».
$result = mysql_query("SELECT * FROM `lessons` LIMIT $art,$kol",$db);
Отлично, теперь создадим переменную $page, она будет показывать текущею страницу, на который мы находимся.
К примеру, мы выводим по две записи на страницу, то есть если мы находимся на 1 странице — выводим первые две записи.
$page = 1; // текущая страница $kol = 3; //количество записей для вывода $art = ($page * $kol) - $kol; // определяем, с какой записи нам выводить $result = mysql_query("SELECT * FROM `lessons` LIMIT $art,$kol",$db);
Переменную $art мы получаем по формуле — количество записей умножаются на текущую страницу, тем самым мы получаем последнюю запись на текущей странице. И вычитаем «количество записей на страницу».
Определяем страницу, на которой находимся
Теперь у нас для нужной страницы отображаются нужные записи, но нужно ещё определить, на какой мы странице находимся, для этого воспользуемся глобальной переменной $_GET.
if (isset($_GET['page']))< $page = $_GET['page']; >else $page = 1;
Мы получаем текущую страницу через переменную $_GET, а если мы этой переменной нет, то у нас по умолчанию первая страница.
Формируем постраничную навигацию
Для формирования и вывода пагинации нам нужно узнать количество всех записей, найдём это через простой запрос:
$res = mysql_query("SELECT COUNT(*) FROM `lessons`"); $row = mysql_fetch_row($res); $total = $row[0]; // всего записей
Затем нужно узнать, сколько у нас будет страниц:
Делим количество записей на количество выводимых на страницу и округляем до большего числа
Теперь у нас есть всё, чтобы сформировать наши ссылки для навигации, выведем через цикл:
Постраничная навигация на PHP
Часто при разработке и выводе контента появляется необходимость использования постраничной навигации. Кто-то скорее всего использует готовые решения от своего фреймворка. Кто-то, возможно, не заморачивается и лупит страницы просто циклом. У кого-то есть свои наработки в этом направлении. Вот я как раз и хочу поделиться своим решением данной задачи.
Существует множество вариаций расположения и отображения кнопок, лично я пришел к следующему решению, которое по моему мнению наиболее наглядно и удобно. Подходит как для 5 страниц так и для 5000.
Пример HTML кода
Не буду ходить вокруг да около, сразу приложу пример сформированного скриптом html кода:
Назад 1 . 4 5 6 7 8 9 10 . 17 Вперед
Логика построения
По настройкам параметров я остановлюсь чуть позже после приведения кода, сейчас опишу логику формирования самих номеров.
С кнопками «Назад» и «Вперед» думаю все понятно, к тому же их можно просто отключить, поэтому на них не буду заострять внимания.
Первый и последний номер страницы отображается всегда, своего рода кнопки «В начало» и «В конец».
Середина формируется уже по простому алгоритму. Отображается просматриваемая страница и по N страниц по бокам. На примере отображается по N=3 страницы. В принципе все просто и понятно, но особая хитрость используется при приближении к краям. Опишу на примерах:
Страница 1-3 (где 3 = N)
Отображаются первые N*2 страниц и последняя.
Отображается первая и дальше сформированная строка от 4-3=1 до 4+3=7. Первая страница зарезервирована поэтому формируются номера от 2 до 7.
Пожалуй во всех навигациях что я видел (включая хабр) строка была бы сформирована с пропуском, т.е. 1… 3 4 5 6 7 8 9… 17
Но ведь это не логично, отображать многоточие вместо одного числа. При построении второго многоточия выполняется аналогичная проверка.
Формирование окончания аналогично началу
Редиректы
Помимо этого из особенностей хочу выделить еще 2 момента, это проверка существования страницы и редирект на «правильный» адрес. Т.е. к примеру, тут же на хабре первая страница может быть доступна сразу по 2м адресам:
habrahabr.ru/sandbox/page1
habrahabr.ru/sandbox
Скрипт не дает зайти на адрес page/1/ и выполняет редирект на «чистый» адрес
Так же если указан слишком большой номер страницы будет выполнен редирект на последнюю существующую. К примеру были удалены материалы или изменено количество записей на страницу. Не могу правда однозначно сказать полезно ли это будет с точки зрения СЕО, но для пользователей мне кажется так будет удобнее.
PHP код и его использование
class PaginateNavigationBuilder < /** * Чистый URL по умолчанию * В адресе может быть указано место для размещения блока с номером страницы, тег * Пример: * /some_url.html * В итоге адрес будет: * /some_url.html * /some_url/page_2.html * Если тег не указан, то страницы будут дописываться в конец адреса * * @var string */ private $baseUrl = '/'; /** * Шаблон ссылки навигации * * @var string */ public $tpl = 'page//'; /** * Обертка кнопок * * @var string */ public $wrap = "baseUrl = $baseUrl; > /** * Строим навигации и формируем шаблон * * @param integer $limit количество записей на 1 страницу * @param integer $count_all общее количество всех записей * @param integer $currentPage номер просматриваемой страницы * @return mixed Сформированный шаблон навигации готовый к выводу */ public function build($limit, $count_all, $currentPage = 1) < if( $limit < 1 OR $count_all $count_pages ) < header( "HTTP/1.0 301 Moved Permanently" ); header( "Location: " . $this->getUrl( $count_pages ) ); die( "Redirect" ); > if( $currentPage == 1 AND $_SERVER['REQUEST_URI'] != $this->getUrl( $currentPage ) ) < header( "HTTP/1.0 301 Moved Permanently" ); header( "Location: " . $this->getUrl( $currentPage ) ); die( "Redirect" ); > $this->currentPage = intval( $currentPage ); if( $this->currentPage < 1 ) $this->currentPage = 1; $shift_start = max( $this->currentPage - $this->spread, 2 ); $shift_end = min( $this->currentPage + $this->spread, $count_pages-1 ); if( $shift_end < $this->spread*2 ) < $shift_end = min( $this->spread*2, $count_pages-1 ); > if( $shift_end == $count_pages - 1 AND $shift_start > 3 ) < $shift_start = max( 3, min( $count_pages - $this->spread*2 + 1, $shift_start ) ); > $list = $this->getItem( 1 ); if ($shift_start == 3) < $list .= $this->getItem( 2 ); > elseif ( $shift_start > 3 ) < $list .= $this->separator; > for( $i = $shift_start; $i getItem( $i ); > $last_page = $count_pages - 1; if( $shift_end == $last_page-1 )< $list .= $this->getItem( $last_page ); > elseif( $shift_end < $last_page ) < $list .= $this->separator; > $list .= $this->getItem( $count_pages ); if( $this->nextPrev ) < $list = $this->getItem( $this->currentPage > 1 ? $this->currentPage - 1 : 1, $this->prevTitle, true ) . $list . $this->getItem( $this->currentPage < $count_pages ? $this->currentPage + 1 : $count_pages, $this->nextTitle, true ); > return str_replace( "", $list, $this->wrap ); > /** * Формирование адреса * @param int $page_num номер страницы * @return string сформированный адрес */ private function getUrl( $page_num = 0 ) < $page = $page_num >1 ? str_replace( '', $page_num, $this->tpl ) : ''; if( stripos( $this->baseUrl, '' ) !== false )< return str_replace( '', $page, $this->baseUrl ); > else < return $this->baseUrl . $page; > > /** * Формирование кнопки/ссылки * @param int $page_num номер страницы * @param string $page_name если указано, будет выводиться текст вместо номера страницы * @param bool $noclass * @return - span блок с активной страницей или ссылку. */ private function getItem( $page_num, $page_name = '', $noclass = false ) < $page_name = $page_name ?: $page_num; $className = $noclass ? '' : $this->activeClass; if( $this->currentPage == $page_num ) < return "else < return "getUrl($page_num)>\"> "; > > >
Для наглядности, приведу пример построения навигации песочницы:
habrahabr.ru/sandbox/page12
$navi = new PaginateNavigationBuilder( "/sandbox/" ); $navi->tpl = "page/"; $navi->spread = 4; $template = $navi->build( $limit, $count_all, $page_num );
Или же если номер страницы прописан внутри URL:
example.com/some_url/1.html — первая страница
example.com/some_url/1-page2.html — вторая страница
$navi = new PaginateNavigationBuilder( "/some_url/1.html" ); $navi->tpl = "-page"; $template = $navi->build( $limit, $count_all, $page_num );
$limit — количество записей на страницу
$count_all — общее количество записей
$page_num — номер страницы на которой находится пользователь
На этом, пожалуй, всё. Буду рад любой конструктивной критике.
PS. Огромное спасибо всем отписавшимся, особенно тем кто ругает (и правильно делает).
Обещаю со всем ознакомиться, принять во внимание и исправиться.