Advertisement
  1. Code
  2. PHP
  3. PHP Scripts

Как разбить данные на страницы с помощью PHP

Scroll to top
Read Time: 10 min

() translation by (you can also view the original English article)

Я вспоминаю, когда много лет назад, когда я только начинал писать код PHP и MySQL, я был весьма рад, когда впервые моя информация из базы данных отобразилась в браузере.

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

Хотя мой уровень в отношении баз данных не таков, как был раньше, сейчас он значительно богаче,
со времени моего первого знакомства с PHP и MySQL, меня пленила
мысль делать вещи более простыми и легкими в использовании.

Как разработчик я постоянно сталкиваюсь с одной проблемой: принятие большого количества информации и попытка легко усвоить ее. Является ли это список клиентов крупной компании или личный mp3-каталог, вынужденность сидеть и смотреть на строку над строкой, строку над строкой разных данных может быть весьма скучным занятием
и даже более - вы можете разочароваться. Что может сделать хороший разработчик? Разбить на страницы!


1. Разбивка на страницы

Разбиение на страницы - это по существу процесс принятия набора результатов и распределение
их по страницам, чтоб их было легче читать.

example 1example 1example 1

Ещё раньше я размышлял, если бы у меня было 500 строчек информации, которую нужно отобразить, это было бы
не только головной болью для того, кто попытается все это прочитать, но и большинство браузеров
потратили бы целую вечность (т.е. более чем пять секунд) на отображение этой информации.

Чтобы решить эту проблему я мог бы написать разные инструкции SQL, чтобы вытащить фрагменты данных, и если бы у меня
было хорошее настроение, я бы даже сделал пару кнопок, «далее» и «предыдущая». 
Через некоторое время, мне нужно было внести этот код в очень похожий проект и настроить
его, чтобы подогнать под старый вариант. Быстро. И как каждый хороший разработчик знает, лень рождает изобретательность
или что-то в этом роде. Поэтому, однажды, я сел и решил придумать простой,
гибкий и легкий в использовании класс PHP, который автоматически бы делал грязную работу
вместо меня.

Несколько слов обо мне и классах PHP. Я не волшебник в сфере объектно-ориентированного программирования. На самом деле, я практически
никогда не использую подобные вещи. Но после прочтения некоторых примеров ООП и учебных материалов, а также
простых примеров проб и ошибок, я решил сделать решительный поворот, и знаете, что?
Он идеально работает для разбивки на страницы. Код, который я здесь использую, написан в PHP 4, но 
он работает и в PHP 5.


2. База данных

Вам нужно любить MySQL. Не хочу обидеть другие системы баз данных, но 
для меня, все что мне нужно - это MySQL. Одной из прекрасных особенностью MySQL является то, что они дают вам
некоторые бесплатные примеры баз данных, с которыми вы можете поиграться: http://dev.mysql.com/doc/#sampledb.

В моем случае я буду использовать всемирную базу данных (архив ~ 90 k), которая содержит
свыше 4000 записей, с которыми можно поработать, но красота PHP-скрипта, который мы будем создавать, в том,
что его можна использовать для любой базы данных. Теперь, думаю, мы все можем согласиться, что если мы решили
не разбивать наши результаты, в итоге мы получим очень длинный и громоздкий
список результатов, как примерно показано ниже:

example 2

(кликните, чтобы получить изображение в полном размере, оно невероятно длинное, ~ 338k)

Потому давайте пойдем дальше, разбивая наши данные в легко обрабатываемые байты, как показано ниже:

example 3example 3example 3

Красиво, не так ли? После того, как вы ввели клас разбивки на страницы в ваш код, вы можете
быстро и просто превратить огромный набор данных в страницы, по которым можно легко перемещаться
с помощью всего нескольких строк кода. Это на самом деле так.


3. Пагинатор

Данный пример будет состоять с двух скриптов, многоразового класса paginator и файла index, который будет выводить элементы таблицы и элементы управления.

Paginator.class.php

Класс рaginator будет иметь только два метода и конструктор, мы будем строить их постепенно, объясняя каждый шаг по мере того, как мы движемся вперед.

1
<?php
2
3
class Paginator {
4
5
     private $_conn;
6
        private $_limit;
7
        private $_page;
8
        private $_query;
9
        private $_total;
10
11
}

Это определение только устанавливает необходимые члены-переменные пагинатора. Так как это вспомогательный класс и он разработан только для пагинации, он будет полагаться на валидное подключение к серверу MySQL и на уже определенный запрос, который мы добавим к параметрам, необходимым для разбивки результатов. Мы начнем с метода конструктор.

1
<?php
2
3
public function __construct( $conn, $query ) {
4
    
5
    $this->_conn = $conn;
6
    $this->_query = $query;
7
8
    $rs= $this->_conn->query( $this->_query );
9
    $this->_total = $rs->num_rows;
10
    
11
}

Довольно просто, не так ли? Этот метод только устанавливает соединение базы данных объекта и необходимый запрос, после чего он вычисляет общее количество строк, полученных этим запросом без каких-либо ограничений или пропусков параметров. Эта сумма необходима для создания ссылок для пагинатора.

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

Получение результатов

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

1
<?php
2
public function getData( $limit = 10, $page = 1 ) {
3
    
4
    $this->_limit   = $limit;
5
    $this->_page    = $page;
6
7
    if ( $this->_limit == 'all' ) {
8
        $query      = $this->_query;
9
    } else {
10
        $query      = $this->_query . " LIMIT " . ( ( $this->_page - 1 ) * $this->_limit ) . ", $this->_limit";
11
    }
12
    $rs             = $this->_conn->query( $query );
13
14
    while ( $row = $rs->fetch_assoc() ) {
15
        $results[]  = $row;
16
    }
17
18
    $result         = new stdClass();
19
    $result->page   = $this->_page;
20
    $result->limit  = $this->_limit;
21
    $result->total  = $this->_total;
22
    $result->data   = $results;
23
24
    return $result;
25
}

Давайте сейчас проанализируем этот шаг: сначала мы установили лимит и параметры страницы, которые по умолчанию установлены на 10 и 1 соответственно. Далее мы проверяем, запрашивает ли пользователь заданное число строк или все из них и, основываясь на этом и на параметрах страницы, мы устанавливаем параметр LIMIT этого запроса. Значение "-1" берется с учётом того, что мы начинаем нумерацию страницы  с 1, но не с 0.

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

Отображение пагинальных ссылок

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

1
<?php
2
public function createLinks( $links, $list_class ) {
3
    if ( $this->_limit == 'all' ) {
4
        return '';
5
    }
6
7
    $last       = ceil( $this->_total / $this->_limit );
8
9
    $start      = ( ( $this->_page - $links ) > 0 ) ? $this->_page - $links : 1;
10
    $end        = ( ( $this->_page + $links ) < $last ) ? $this->_page + $links : $last;
11
12
    $html       = '<ul class="' . $list_class . '">';
13
14
    $class      = ( $this->_page == 1 ) ? "disabled" : "";
15
    $html       .= '<li class="' . $class . '"><a href="?limit=' . $this->_limit . '&page=' . ( $this->_page - 1 ) . '">&laquo;</a></li>';
16
17
    if ( $start > 1 ) {
18
        $html   .= '<li><a href="?limit=' . $this->_limit . '&page=1">1</a></li>';
19
        $html   .= '<li class="disabled"><span>...</span></li>';
20
    }
21
22
    for ( $i = $start ; $i <= $end; $i++ ) {
23
        $class  = ( $this->_page == $i ) ? "active" : "";
24
        $html   .= '<li class="' . $class . '"><a href="?limit=' . $this->_limit . '&page=' . $i . '">' . $i . '</a></li>';
25
    }
26
27
    if ( $end < $last ) {
28
        $html   .= '<li class="disabled"><span>...</span></li>';
29
        $html   .= '<li><a href="?limit=' . $this->_limit . '&page=' . $last . '">' . $last . '</a></li>';
30
    }
31
32
    $class      = ( $this->_page == $last ) ? "disabled" : "";
33
    $html       .= '<li class="' . $class . '"><a href="?limit=' . $this->_limit . '&page=' . ( $this->_page + 1 ) . '">&raquo;</a></li>';
34
35
    $html       .= '</ul>';
36
37
    return $html;
38
}

Это довольно длинный метод, примерно на 34 строки кода, потому давайте объясним, что как происходит в этом методе.

  1. Сначала мы оцениваем, требует ли пользователь заданное количество ссылок или все из них, в противном случае, мы просто возвращаем пустую строку, так как пагинация не требуется.
  2. После этого мы вычисляем последнюю страницу на основе общего количества доступных строк и элементов, необходимых для каждой страницы.
  3. После этого мы берем параметры ссылок, которые отображают количество ссылок, которые нужно разместить вверху и внизу текущей страницы и вычисляем, когда создать начальную и конечную ссылку.
  4. Теперь мы создаем открывающий тег для списка и устанавливаем для него параметр класса и добавляем ссылку "предыдущая страница". Обратите внимание, что для этой ссылки мы проверяем, является ли текущая страница первой, и если да, то мы устанавливаем для ссылки свойство "недоступен".
  5. На данный момент мы отображаем ссылку на первой странице и символ многоточия в случае, если начальная ссылка не является первой.
  6. Затем мы добавляем ссылки ниже и выше текущей страницы, исходя из ранее вычисленных начальных и конечных параметров. На каждом шагу мы снова оцениваем текущую страницу, отображаемую страницу ссылки, и соответственно устанавливаем активный класс.
  7. После этого мы отображаем другой символ многоточия и ссылку на последнюю страницу в случае, если конечная ссылка не есть последняя.
  8. Наконец мы показываем ссылку «Следующая страница» и устанавливаем отключенное состояние, когда пользователь просматривает последнюю страницу. Закройте список и вернитесь на сгенерированную строку HTML.

Это все, что касается Paginator.class. Конечно, мы могли бы добавить сеттеры и геттеры для подключения к базе данных, ограничения, страницы, запрос и полные параметры, но для простоты мы сохраним его таким как есть.

4. Index.php

Теперь мы создадим файл, отвечающий за использование класса Paginator и отображение данных, поэтому сначала позвольте мне показать вам базовый HTML.

1
<!DOCTYPE html>
2
    <head>
3
        <title>PHP Pagination</title>
4
        <link rel="stylesheet" href="css/bootstrap.min.css">
5
    </head>
6
    <body>
7
        <div class="container">
8
                <div class="col-md-10 col-md-offset-1">
9
                <h1>PHP Pagination</h1>
10
                <table class="table table-striped table-condensed table-bordered table-rounded">
11
                        <thead>
12
                                <tr>
13
                                <th>City</th>
14
                                <th width="20%">Country</th>
15
                                <th width="20%">Continent</th>
16
                                <th width="25%">Region</th>
17
                        </tr>
18
                        </thead>
19
                        <tbody></tbody>
20
                </table>
21
                </div>
22
        </div>
23
        </body>
24
</html>

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

Использование пагинатора

1
<?php for( $i = 0; $i < count( $results->data ); $i++ ) : ?>
2
        <tr>
3
                <td><?php echo $results->data[$i]['Name']; ?></td>
4
                <td><?php echo $results->data[$i]['Country']; ?></td>
5
                <td><?php echo $results->data[$i]['Continent']; ?></td>
6
                <td><?php echo $results->data[$i]['Region']; ?></td>
7
        </tr>
8
<?php endfor; ?>

Теперь, чтобы воспользоваться классом пагинатора, добавьте следующий РНР-код в верхней части документа.

1
<?php
2
    require_once 'Paginator.class.php';
3
4
    $conn       = new mysqli( '127.0.0.1', 'root', 'root', 'world' );
5
6
    $limit      = ( isset( $_GET['limit'] ) ) ? $_GET['limit'] : 25;
7
    $page       = ( isset( $_GET['page'] ) ) ? $_GET['page'] : 1;
8
    $links      = ( isset( $_GET['links'] ) ) ? $_GET['links'] : 7;
9
    $query      = "SELECT City.Name, City.CountryCode, Country.Code, Country.Name AS Country, Country.Continent, Country.Region FROM City, Country WHERE City.CountryCode = Country.Code";
10
11
    $Paginator  = new Paginator( $conn, $query );
12
13
    $results    = $Paginator->getData( $page, $limit );
14
?>

Этот скрипт достаточно прост. Мы просто вызвали класс пагинатор, обратите внимание, что этот код предполагает, что этот файл находится в той же папке, что и файл index.php. Если это не так, вы должны соответствующим образом обновить путь.

Затем мы создаем соединение с нашей базой данных с помощью библиотеки MySQLi, извлекаем параметры пагинатора из запроса GET и устанавливаем запрос, так как это не статья на MySQL или что-либо другое, во что я не буду вдаваться в подробности.

Наконец, мы создали объект Paginator и извлекли результаты для текущей страницы.

Отображение результатов

Теперь, чтобы отобразить полученные результаты, добавьте следующий код в тело таблицы.

1
<?php for( $i = 0; $i < count( $results->data ); $i++ ) : ?>
2
        <tr>
3
                <td><?php echo $results->data[$i]['Name']; ?></td>
4
                <td><?php echo $results->data[$i]['Country']; ?></td>
5
                <td><?php echo $results->data[$i]['Continent']; ?></td>
6
                <td><?php echo $results->data[$i]['Region']; ?></td>
7
        </tr>
8
<?php endfor; ?>

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

Ссылки пагинации

Теперь, чтобы отобразить ссылки пагинатора,  добавьте следующий код ниже таблицы.

1
<?php echo $Paginator->createLinks( $links, 'pagination pagination-sm' ); ?> 

Для метода Paginator createLinks мы передаем полученный параметр links и класс css для ссылок пагинации, использованных на bootstrap. Вот результат созданной страницы.

Заключение

Этот материал должен обеспечить вас всем, что вам нужно, чтобы осуществить пагинацию в вашем приложении.

Пожалуйста, не стесняйтесь, оставляйте ниже ваши вопросы, комментарии или обобщенный отзыв!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.