Постраничный вывод на PHP и MySQL
Пагинация помогает удобно разделять данные на страницы и упрощает работу с таблицами. Такой подход делает навигацию по большим массивам информации наглядной и удобной.
В этом материале мы разберем создание удобного класса для постраничного вывода в PHP и MySQL. Вы узнаете, как настроить автоматическую генерацию ссылок на страницы, научитесь гибко управлять параметрами пагинации и сможете быстро выводить данные из базы в понятном и аккуратном формате.
Создание таблицы базы данных
Следующий SQL-запрос создаёт таблицу posts в базе данных MySQL с основными столбцами.
CREATE TABLE `posts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=Active, 0=Inactive',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;Класс Pagination
Класс Pagination генерирует ссылки на страницы. Для настройки вида ссылок доступны различные параметры конфигурации PHP пагинации страниц.
- $baseURL–URL веб-страницы.
- $totalRows–общееколичествоэлементов.
- $perPage–количествозаписейнастранице.
- $numLinks–количествоотображаемыхссылок.
- $firstLink–текстссылкинапервуюстраницу.
- $nextLink–текстссылкинаследующуюстраницу.
- $prevLink–текстссылкинапредыдущуюстраницу.
- $lastLink–текстссылкинапоследнююстраницу.
- $fullTagOpen–открывающийтэгблокассылок.
- $fullTagClose–закрывающийтэгблокассылок.
- $firstTagOpen–открывающийтэгпервогоэлемента.
- $firstTagClose–закрывающийтэгпервогоэлемента.
- $lastTagOpen–открывающийтэгпоследнегоэлемента.
- $lastTagClose–закрывающийтэгпоследнегоэлемента.
- $curTagOpen–открывающийтэгтекущегоэлемента.
- $curTagClose–закрывающийтэгтекущегоэлемента.
- $nextTagOpen–открывающийтэгследующегоэлемента.
- $nextTagClose–закрывающийтэгследующегоэлемента.
- $prevTagOpen–открывающийтэгпредыдущегоэлемента.
- $prevTagClose–закрывающийтэгпредыдущегоэлемента.
- $numTagOpen–открывающийтэгчисловогоэлемента.
- $numTagClose–закрывающийтэгчисловогоэлемента.
- $showCount–показыватьколичествостраниц.
- $queryStringSegment–флагстрокизапросастраницыприпагинации PHP MySQL.
<?php
/**
* CodexWorld
*
* Этот класс помогает интегрировать разбиение на страницы в PHP.
*
* @class Pagination
* @author CodexWorld
* @link http://www.codexworld.com
* @license http://www.codexworld.com/license
* @version 1.0
*/
class Pagination{
protected $baseURL = '';
protected $totalRows = '';
protected $perPage = 10;
protected $numLinks = 2;
protected $currentPage = 0;
protected $firstLink = 'Первая';
protected $nextLink = 'Следующая »';
protected $prevLink = '« Предыдущая';
protected $lastLink = 'Последняя';
protected $fullTagOpen = '<div class="pagination">';
protected $fullTagClose = '</div>';
protected $firstTagOpen = '';
protected $firstTagClose= ' ';
protected $lastTagOpen = ' ';
protected $lastTagClose = '';
protected $curTagOpen = ' <b>';
protected $curTagClose = '</b>';
protected $nextTagOpen = ' ';
protected $nextTagClose = ' ';
protected $prevTagOpen = ' ';
protected $prevTagClose = '';
protected $numTagOpen = ' ';
protected $numTagClose = '';
protected $showCount = true;
protected $currentOffset= 0;
protected $queryStringSegment = 'page';
function __construct($params = array()){
if (count($params) > 0){
$this->initialize($params);
}
}
function initialize($params = array()){
if (count($params) > 0){
foreach ($params as $key => $val){
if (isset($this->$key)){
$this->$key = $val;
}
}
}
}
/**
* Генерируем ссылки на страницы
*/
function createLinks(){
// Если общее количество записей 0, не продолжать
if ($this->totalRows == 0 || $this->perPage == 0){
return '';
}
// Считаем общее количество страниц
$numPages = ceil($this->totalRows / $this->perPage);
// Если страница только одна, не продолжать
if ($numPages == 1){
if ($this->showCount){
$info = 'Showing : ' . $this->totalRows;
return $info;
}else{
return '';
}
}
// Определяем строку запроса
$query_string_sep = (strpos($this->baseURL, '?') === FALSE) ? '?page=' : '&page=';
$this->baseURL = $this->baseURL.$query_string_sep;
// Определяем текущую страницу
$this->currentPage = $_GET[$this->queryStringSegment];
if (!is_numeric($this->currentPage) || $this->currentPage == 0){
$this->currentPage = 1;
}
// Строковая переменная вывода контента
$output = '';
// Отображаем сообщение о ссылках на другие страницы
if ($this->showCount){
$currentOffset = ($this->currentPage > 1)?($this->currentPage - 1)*$this->perPage:$this->currentPage;
$info = 'Показаны элементы с ' . $currentOffset . ' по ' ;
if( ($currentOffset + $this->perPage) < $this->totalRows )
$info .= $this->currentPage * $this->perPage;
else
$info .= $this->totalRows;
$info .= ' из ' . $this->totalRows . ' | ';
$output .= $info;
}
$this->numLinks = (int)$this->numLinks;
// Если номер страницы больше максимального значения, отображаем последнюю страницу
if($this->currentPage > $this->totalRows){
$this->currentPage = $numPages;
}
$uriPageNum = $this->currentPage;
// Рассчитываем первый и последний элементы
$start = (($this->currentPage - $this->numLinks) > 0) ? $this->currentPage - ($this->numLinks - 1) : 1;
$end = (($this->currentPage + $this->numLinks) < $numPages) ? $this->currentPage + $this->numLinks : $numPages;
// Выводим ссылку на первую страницу
if($this->currentPage > $this->numLinks){
$firstPageURL = str_replace($query_string_sep,'',$this->baseURL);
$output .= $this->firstTagOpen.'<a href="'.$firstPageURL.'">'.$this->firstLink.'</a>'.$this->firstTagClose;
}
// Выводим ссылку на предыдущую страницу
if($this->currentPage != 1){
$i = ($uriPageNum - 1);
if($i == 0) $i = '';
$output .= $this->prevTagOpen.'<a href="'.$this->baseURL.$i.'">'.$this->prevLink.'</a>'.$this->prevTagClose;
}
// Выводим цифровые ссылки
for($loop = $start -1; $loop <= $end; $loop++){
$i = $loop;
if($i >= 1){
if($this->currentPage == $loop){
$output .= $this->curTagOpen.$loop.$this->curTagClose;
}else{
$output .= $this->numTagOpen.'<a href="'.$this->baseURL.$i.'">'.$loop.'</a>'.$this->numTagClose;
}
}
}
// Выводим ссылку на следующую страницу
if($this->currentPage < $numPages){
$i = ($this->currentPage + 1);
$output .= $this->nextTagOpen.'<a href="'.$this->baseURL.$i.'">'.$this->nextLink.'</a>'.$this->nextTagClose;
}
// Выводим ссылку на последнюю страницу
if(($this->currentPage + $this->numLinks) < $numPages){
$i = $numPages;
$output .= $this->lastTagOpen.'<a href="'.$this->baseURL.$i.'">'.$this->lastLink.'</a>'.$this->lastTagClose;
}
// Удаляем двойные косые
$output = preg_replace("#([^:])//+#", "\1/", $output);
// Добавляем открывающий и закрывающий тэги блока
$output = $this->fullTagOpen.$output.$this->fullTagClose;
return $output;
}
}Простой пример использования класса пагинации PHP. Сначала включите и инициализируйте класс Pagination с некоторыми базовыми настройками.
<?php
//подключаем файл класса pagination
include_once 'Pagination.class.php';
//инициализируем класс
$pagConfig = array(
'baseURL'=>'http://localhost/php_pagination/index.php',
'totalRows'=>$rowCount,
'perPage'=>$limit
);
$pagination = new Pagination($pagConfig);
?>Чтобы отобразить ссылки на страницы, используйте метод createLinks().
<!-- отображаем ссылки на страницы -->
<?php echo $pagination->createLinks(); ?>Конфигурация базы данных (dbConfig.php)
Файл dbConfig.php используется для соединения с MySQL и выбора базы данных для пагинации PHP. Укажите параметры хост ($dbHost ), имя пользователя ($dbUsername ), пароль ($dbPassword ), и имя базы данных ($dbName ) в соответствии с требованиями вашего сервера баз данных.
<?php
// Конфигурация базы данных
$dbHost = "localhost";
$dbUsername = "root";
$dbPassword = "*****";
$dbName = "codexworld";
// Создаём соединение с базой данных
$db = new mysqli($dbHost, $dbUsername, $dbPassword, $dbName);
// Проверяем соединение
if ($db->connect_error) {
die("Connection failed: " . $db->connect_error);
}
?>Отображение данных с разбиением на страницы (index.php)
В файле index.php ограниченный набор постов будет запрашиваться из базы данных, и отображаться вместе со ссылками на другие страницы. Для PHP пагинации страниц нужно создать объект класса Pagination и передать базовые параметры, чтобы сгенерировать ссылки на страницы. Чтобы отобразить ссылки, используйте метод createLinks().
<?php
//включаем файл класса pagination
include_once 'Pagination.class.php';
//включаем файл конфигурации базы данных
include_once 'dbConfig.php';
$limit = 5;
$offset = !empty($_GET['page'])?(($_GET['page']-1)*$limit):0;
//получаем количество записей
$queryNum = $db->query("SELECT COUNT(*) as postNum FROM posts");
$resultNum = $queryNum->fetch_assoc();
$rowCount = $resultNum['postNum'];
//инициализируем класс pagination
$pagConfig = array(
'baseURL'=>'http://localhost/php_pagination/index.php',
'totalRows'=>$rowCount,
'perPage'=>$limit
);
$pagination = new Pagination($pagConfig);
//получаем записи
$query = $db->query("SELECT * FROM posts ORDER BY id DESC LIMIT $offset,$limit");
if($query->num_rows > 0){ ?>
<div class="posts_list">
<?php while($row = $query->fetch_assoc()){ ?>
<div class="list_item"><a href="javascript:void(0);"><?php echo $row["title"]; ?></a></div>
<?php } ?>
</div>
<!-- отображаем ссылки на страницы -->
<?php echo $pagination->createLinks(); ?>
<?php } ?>Заключение
Мы реализовали постраничный вывод на PHP и MySQL настолько просто, насколько это только возможно. Вы можете расширить функциональность этого класса.
Посмотреть демо
Комментарии
Это, естественно на последних страницах, на первых всё будет работать как надо
1) почему нельзя было весь скрипт засунуть в 1-3 блока, зачем было КАЖДУЮ СТРОКУ ПИХАТЬ В ОТДЕЛЬНЫЙ ТЕГ
2)"SELECT .. FROM .. LIMIT $offset,$limit" - когда в БД будет, скажем, 50к записей эта пагинация будет обрабатывать запросы по секунды 2, вместо 0.002. По-этому лучше юзать джоины или какой-нибудь другой ворк эраунд.