Как реализовать разбиение на страницы в MySQL с PHP на Ubuntu 18.04

Автор выбралthe Apache Software Foundation для получения пожертвования в рамках программыWrite for DOnations.

Вступление

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

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

В этом руководстве вы создадите скриптPHP для подключения к вашей базе данных и реализуете разбиение на страницы в вашем скрипте с помощьюMySQLLIMIT clause.

Предпосылки

Прежде чем начать, вам понадобится следующее:

[[step-1 -—- create-a-database-user-and-a-test-database]] == Шаг 1. Создание пользователя базы данных и тестовой базы данных

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

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

Для начала авторизуйтесь на вашем сервере. Затем войдите в свой сервер MySQL с помощью следующей команды:

sudo mysql -u root -p

Введите парольroot вашего сервера MySQL и нажмитеENTER, чтобы продолжить. Затем вы увидите приглашение MySQL. Чтобы создать образец базы данных, который в этом руководстве мы назовемtest_db, выполните следующую команду:

Create database test_db;

Вы увидите следующий вывод:

OutputQuery OK, 1 row affected (0.00 sec)

Затем создайтеtest_user и предоставьте пользователю все привилегии дляtest_db. ЗаменитеPASSWORD сильным значением:

GRANT ALL PRIVILEGES ON test_db.* TO 'test_user'@'localhost' IDENTIFIED BY 'PASSWORD';
OutputQuery OK, 1 row affected (0.00 sec)

Перезагрузите привилегии MySQL с помощью:

FLUSH PRIVILEGES;
OutputQuery OK, 1 row affected (0.00 sec)

Затем переключитесь на базу данныхtest_db, чтобы начать работу непосредственно с базой данныхtest_db:

Use test_db;
OutputDatabase changed

Теперь создайте таблицуproducts. Таблица будет содержать ваши образцы продуктов - для этого урока вам понадобятся только два столбца для данных. Столбецproduct_id будет служить первичным ключом для уникальной идентификации каждой записи. Вы будете использовать полеproduct_name, чтобы различать каждый элемент по имени:

Create table products (product_id BIGINT PRIMARY KEY, product_name VARCHAR(50) NOT NULL ) Engine = InnoDB;
OutputQuery OK, 0 rows affected (0.02 sec)

Чтобы добавить десять тестовых продуктов в таблицуproducts, выполните следующие операторы SQL:

Insert into products(product_id, product_name) values ('1', 'WIRELESS MOUSE');
Insert into products(product_id, product_name) values ('2', 'BLUETOOTH SPEAKER');
Insert into products(product_id, product_name) values ('3', 'GAMING KEYBOARD');
Insert into products(product_id, product_name) values ('4', '320GB FAST SSD');
Insert into products(product_id, product_name) values ('5', '17 INCHES TFT');
Insert into products(product_id, product_name) values ('6', 'SPECIAL HEADPHONES');
Insert into products(product_id, product_name) values ('7', 'HD GRAPHIC CARD');
Insert into products(product_id, product_name) values ('8', '80MM THERMAL PRINTER');
Insert into products(product_id, product_name) values ('9', 'HDMI TO VGA CONVERTER');
Insert into products(product_id, product_name) values ('10', 'FINGERPRINT SCANNER');

Вы увидите этот вывод:

OutputQuery OK, 1 row affected (0.02 sec)

Убедитесь, что продукты были вставлены в таблицу, выполнив:

select * from products;

Вы увидите продукты в выходных данных в двух столбцах:

Output+------------+-----------------------+
| product_id | product_name          |
+------------+-----------------------+
|          1 | WIRELESS MOUSE        |
|          2 | BLUETOOTH SPEAKER     |
|          3 | GAMING KEYBOARD       |
|          4 | 320GB FAST SSD        |
|          5 | 17 INCHES TFT         |
|          6 | SPECIAL HEADPHONES    |
|          7 | HD GRAPHIC CARD       |
|          8 | 80MM THERMAL PRINTER  |
|          9 | HDMI TO VGA CONVERTER |
|         10 | FINGERPRINT SCANNER   |
+------------+-----------------------+
10 rows in set (0.00 sec)

Выход из MySQL:

quit;

Имея образец базы данных, таблицы и данные испытаний, вы можете теперь создать сценарий PHP для отображения данных на веб-странице.

[[step-2 -—- displaying-mysql-records-without-pagination]] == Шаг 2 - Отображение записей MySQL без разбивки на страницы

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

Создайте файл сценария PHP в корневом каталоге документа с помощью следующей команды:

sudo nano /var/www/html/pagination_test.php

Затем добавьте следующее содержимое в файл. Не забудьте заменитьPASSWORD правильным значением пароля, который вы присвоилиtest_user на предыдущем шаге:

/var/www/html/pagination_test.php

setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);

    $sql="select * from products";

    $stmt = $pdo->prepare($sql);

    $stmt->execute();

    echo "";

    while ( ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) !== false) {
        echo "";

        echo "";

        echo "";

        echo "";

    }

    echo "
".$row['product_id']."".$row['product_name']."
"; } catch(PDOException $e) { echo $e->getMessage(); } ?>

Сохраните файл, нажавCTRL+X,Y иENTER.

В этом сценарии вы подключаетесь к базе данных MySQL с помощью библиотекиPDO (PHP Data Object) с учетными данными базы данных, которые вы создали на шаге 1.

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

Затем вы даете команду PDO API выполнить операторselect * from products и перечислить продукты в таблице HTML без разбивки на страницы. Строка$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); гарантирует, что типы данных возвращаются в том виде, в каком они появляются в базе данных. Это означает, что PDO вернетproduct_id в виде целого числа иproduct_name в виде строки. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); указывает PDO генерировать исключение при обнаружении ошибки. Для упрощения отладки вы обнаруживаете ошибку внутри блока PHPtry{}...catch{}.

Чтобы выполнить созданный вами файл сценария PHP/var/www/html/pagination_test.php, перейдите по следующему URL-адресу, заменивyour-server-IP общедоступным IP-адресом вашего сервера:

http://your-server-IP/pagination_test.php

Вы увидите страницу с таблицей ваших продуктов.

MySQL Records Displayed with a PHP script - No Pagination

Ваш PHP скрипт работает как положено; перечисление всех продуктов на одной странице. Если у вас есть тысячи продуктов, это приведет к длинному циклу, так как продукты выбираются из базы данных и отображаются на странице PHP.

Чтобы преодолеть это ограничение, вы измените сценарий PHP и включите предложение MySQLLIMIT и некоторые навигационные ссылки в нижней части таблицы, чтобы добавить функциональность разбивки на страницы.

[[step-3 -—- implementation-pagination-with-php]] == Шаг 3. Реализация разбивки на страницы с помощью PHP

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

Для этого вам нужно реализовать предложение MySQLLIMIT. Прежде чем добавлять это в скрипт, давайте посмотрим на пример синтаксиса MySQLLIMIT:

Select [column1, column2, column n...] from [table name] LIMIT offset, records;

ПредложениеLIMIT принимает два аргумента, как показано в конце этого оператора. Значениеoffset - это количество записей, которые нужно пропустить перед первой строкой. records устанавливает максимальное количество записей для отображения на странице.

Чтобы проверить нумерацию страниц, на странице будет отображаться три записи. Чтобы получить общее количество страниц, вы должны разделить общее количество записей из вашей таблицы на строки, которые вы хотите отобразить на странице. Затем округлите полученное значение до ближайшего целого числа с помощью функции PHPCeil, как показано в следующем примере фрагмента кода PHP:

$total_pages=ceil($total_records/$per_page);

Ниже приведена модифицированная версия скрипта PHP с полным кодом пагинации. Чтобы включить коды пагинации и навигации, откройте файл/var/www/html/pagination_test.php:

sudo nano /var/www/html/pagination_test.php

Затем добавьте следующий выделенный код в ваш файл:

/var/www/html/pagination_test.php

setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);

    /* Begin Paging Info */

    $page=1;

    if (isset($_GET['page'])) {
        $page=filter_var($_GET['page'], FILTER_SANITIZE_NUMBER_INT);
    }

    $per_page=3;

    $sqlcount="select count(*) as total_records from products";
    $stmt = $pdo->prepare($sqlcount);
    $stmt->execute();
    $row = $stmt->fetch();
    $total_records= $row['total_records'];

    $total_pages=ceil($total_records/$per_page);

    $offset=($page-1)*$per_page;

    /* End Paging Info */

    $sql="select * from products limit $offset,$per_page";

    $stmt = $pdo->prepare($sql);

    $stmt->execute();


    echo "";

    while ( ($row = $stmt->fetch(PDO::FETCH_ASSOC) ) !== false) {
        echo "";

        echo "";

        echo "";

        echo "";

    }

    echo "
".$row['product_id']."".$row['product_name']."
"; /* Begin Navigation */ echo ""; echo ""; if( $page-1>=1) { echo ""; } if( $page+1<=$total_pages) { echo ""; } echo ""; echo "
PreviousNext
"; /* End Navigation */ } catch(PDOException $e) { echo $e->getMessage(); } ?>

В вашем файле вы использовали дополнительные параметры для пейджинга:

  • $page: эта переменная содержит текущую страницу в вашем скрипте. При перемещении между страницами ваш сценарий извлекает параметр URL с именемpage, используя переменную$_GET['page'].

  • $per_page: эта переменная содержит максимальное количество записей, которые вы хотите отображать на странице. В вашем случае вы хотите перечислить три продукта на каждой странице.

  • $total_records: перед тем, как перечислить продукты, вы выполняете оператор SQL, чтобы получить общее количество записей в целевой таблице и присваивать его переменной$total_records.

  • $offset: эта переменная представляет общее количество записей, которые нужно пропустить перед первой строкой. Это значение рассчитывается динамически вашим PHP-скриптом по формуле$offset=($page-1)*$per_page. Вы можете адаптировать эту формулу к своим проектам разбиения на страницы PHP. Помните, что вы можете изменить переменную$per_page по своему усмотрению. Например, вы можете изменить его на значение50, чтобы отображать пятьдесят элементов на странице, если у вас есть веб-сайт, или другое количество для мобильного устройства.

Снова зайдите на свой IP-адрес в браузере и заменитеyour_server_ip публичным IP-адресом вашего сервера:

http://your_server_ip/pagination_test.php

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

MySQL Records Displayed with a PHP script with Pagination - Page 1

MySQL Records Displayed with a PHP script with Pagination - Page 2

Final page of MySQL Records Displayed with a PHP script with Pagination - Page 4

Навигационные ссылки внизу страницы выполняются с использованием следующего фрагмента кода PHP из вашего файла:

/var/www/html/pagination_test.php

. . .
    if( $page-1>=1) {
        echo "Previous";
    }

    if( $page+1<=$total_pages) {
        echo "Next";
    }
. . .

Здесь переменная$page представляет номер текущей страницы. Затем, чтобы перейти на предыдущую страницу, код вычтет1 из переменной. Итак, если вы находитесь на странице 2, формула(2-1) даст вам результат1, и это будет предыдущая страница, которая появится в ссылке. Однако имейте в виду, что предыдущая страница будет отображаться только в том случае, если результат будет больше или равен1.

Точно так же, чтобы перейти на следующую страницу, вы добавляете единицу к переменной$page, и вы также должны убедиться, что результат$page, который мы добавляем к параметру URLpage, не превышает общее количество страниц, которое вы рассчитали в своем PHP-коде.

На этом этапе ваш сценарий PHP работает с разбиением на страницы, и вы можете реализовать предложение MySQLLIMIT для лучшей навигации по записям.

Заключение

В этом руководстве вы реализовали подкачку в MySQL с помощью PHP на сервере Ubuntu 18.04. Вы можете использовать эти шаги с большим набором записей, используя PHP-скрипт для включения нумерации страниц. Используя нумерацию страниц на своем веб-сайте или в приложении, вы можете улучшить навигацию пользователей и оптимальное использование ресурсов на своем сервере.

Отсюда вы можете рассмотреть дальнейшую оптимизацию вашей базы данных и другие задачи базы данных с этими учебниками:

Related