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

Пагинация PHP позволяет разделять данные по частям и получить ссылки на страницы. В этом руководстве мы расскажем, как создать простое разбиение на страницы в PHP и MySQL. Чтобы обеспечить повторное использование скрипта, мы создадим класс Pagination.

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

Перед тем, как мы начнём, взгляните на структуру файлов проекта.

  • php_pagination/
    • class.php
    • php
    • php

Создание таблицы базы данных

Следующий 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     = 'Следующая &raquo;';
     protected $prevLink     = '&laquo; Предыдущая';
     protected $lastLink     = 'Последняя';
     protected $fullTagOpen  = '<div class="pagination">';
     protected $fullTagClose = '</div>';
     protected $firstTagOpen = '';
     protected $firstTagClose= '&nbsp;';
     protected $lastTagOpen  = '&nbsp;';
     protected $lastTagClose = '';
     protected $curTagOpen   = '&nbsp;<b>';
     protected $curTagClose  = '</b>';
     protected $nextTagOpen  = '&nbsp;';
     protected $nextTagClose = '&nbsp;';
     protected $prevTagOpen  = '&nbsp;';
     protected $prevTagClose = '';
     protected $numTagOpen   = '&nbsp;';
     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=' : '&amp;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 настолько просто, насколько это только возможно. Вы можете расширить функциональность этого класса.

Посмотреть демо

Сергей Бензенкоавтор-переводчик статьи «Pagination in PHP with MySQL»