Advertisement
  1. Code
  2. PHP

Як розбивати дані за допомогою PHP

Scroll to top
Read Time: 10 min

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

Я пам'ятаю, як багато років тому, коли я тільки починав писати код РНР і 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 записів, з якими можна попрацювати. Але краса РНР-скрипта, який ми будемо використовувати, в тому,
що його можна використовувати для будь-якої бази даних. Думаю, тепер ми всі можемо погодитись, що якщо ми вирішили
не розбивати наші результати, в кінці кінців ми отримаємо дуже довгий і громіздкими
список результатів, як для прикладу показано нижче:

example 2

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

Тому давайте підемо далі, розбиваючи наші дані на байти, які легко оброблювати:

example 3example 3example 3

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


3. Рaginator

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

Paginator.Class.php

Клас paginator буде мати тільки два метода і конструктор, ми будемо будувати їх поступово, пояснюючи кожний крок по мірі просування вперед.

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

Це визначення тільки встановлює необхідні змінні-члени paginator. Оскільки це допоміжний клас і він розроблений тільки для пагінації, він буде покладатися на валідне підключення до сервера 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
}

Досить просто, чи не так? Цей метод тільки встановлює з'єднання об'єкта бази даних і необхідного запиту, після чого він обчислює необхідну кількість рядків, отриманих через цей запит без будь-яких обмежень і пропусків параметрів. Ця сумма необхідна для створення посилань на paginator.

Зверніть увагу, що для спрощення ми не виконуємо перевірку помилок або будь-яку іншу перевірку даних параметрів, але в реальності така перевірка необхідна.

Отримання результатів

Тепер давайте створимо метод, який фактично буде розбивати дані і повертати результати.

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. Іndex. 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; ?>

Тепер, щоб скористатися класом Paginator, додайте наступний РНР-код в верхній частині документа.

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
?>

Цей скрипт досить простий. Ми всього лиш викликали клас Paginator. Зверінть увагу, що даний код підрозуміває, що цей файл знаходиться в тій же папці, що і файл 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.