В 31 уроке мы разберем, как реализовать пагинацию на PHP. Пагинация это механизм разделения данных на страницы. Представьте, у вас есть таблица с 1000 записей. Выводить все разом, плохая идея. Это замедлит загрузку страницы, перегрузит сервер и запутает пользователя. Пагинация решает эту проблему, разбивая данные на «порции» и позволяя переключаться между ними.
В этом уроке мы научимся:
- Рассчитывать общее количество страниц.
- Работать с параметрами
LIMIT
иOFFSET
в SQL. - Создавать навигационные ссылки для переключения страниц.
- Защищаться от некорректных значений.
Как работает пагинация?
Основные шаги:
- Получить общее количество записей из базы данных.
- Определить, сколько элементов показывать на странице (например, 10).
- Рассчитать общее количество страниц:
$total_pages = ceil($total_records / $records_per_page);
- Получить номер текущей страницы из URL (например,
?page=2
). - Выбрать данные для текущей страницы с помощью SQL-запроса с
LIMIT
иOFFSET
.
Реализация пагинации
Шаг 1. Подключение к базе данных
Для начала подключимся к базе данных. Я использую MySQLi, но вы можете выбрать PDO.
$servername = "localhost"; $username = "root"; $password = ""; $dbname = "test_db"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("Ошибка подключения: " . $conn->connect_error); }
Шаг 2. Получаем общее количество записей
$sql = "SELECT COUNT(id) AS total FROM products"; $result = $conn->query($sql); $row = $result->fetch_assoc(); $total_records = $row['total']; // Общее количество товаров
Шаг 3. Настраиваем пагинацию
$records_per_page = 10; // Товаров на странице $current_page = isset($_GET['page']) ? (int)$_GET['page'] : 1; // Текущая страница // Защита от отрицательных значений и превышения общего числа страниц if ($current_page < 1) { $current_page = 1; } $total_pages = ceil($total_records / $records_per_page); if ($current_page > $total_pages) { $current_page = $total_pages; } // Расчет OFFSET для SQL-запроса $offset = ($current_page - 1) * $records_per_page;
Шаг 4. Запрос данных для текущей страницы
$sql = "SELECT * FROM products LIMIT $records_per_page OFFSET $offset"; $result = $conn->query($sql); // Вывод данных while ($row = $result->fetch_assoc()) { echo "<div>{$row['name']} - {$row['price']} руб.</div>"; }
Шаг 5. Вывод навигации
Создадим ссылки для переключения страниц:
echo "<div class='pagination'>"; // Кнопка "Назад" if ($current_page > 1) { echo "<a href='?page=" . ($current_page - 1) . "'>Назад</a>"; } // Нумерация страниц for ($i = 1; $i <= $total_pages; $i++) { $active = ($i == $current_page) ? " class='active'" : ""; echo "<a href='?page=$i'$active>$i</a>"; } // Кнопка "Вперед" if ($current_page < $total_pages) { echo "<a href='?page=" . ($current_page + 1) . "'>Вперед</a>"; } echo "</div>";
Дополнительные советы
Защита от SQL-инъекций
Всегда проверяйте и фильтруйте входные данные. Например, номер страницы должен быть целым числом:
$current_page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT, ['options' => ['default' => 1, 'min_range' => 1]]);
Стилизация пагинации
Добавьте CSS, чтобы навигация выглядела привлекательно:
.pagination a { display: inline-block; padding: 8px 16px; margin: 0 4px; border: 1px solid #ddd; text-decoration: none; color: #333; } .pagination a.active { background-color: #007bff; color: white; border-color: #007bff; }
Практические задачи
Задача 1. Реализуйте пагинацию для таблицы пользователей.
- Показывать по 5 пользователей на странице.
- Добавьте кнопки «В начало» и «В конец».
Решение для задачи 1:
// Кнопка "В начало" if ($current_page > 1) { echo "<a href='?page=1'>В начало</a>"; } // ... остальной код ... // Кнопка "В конец" if ($current_page < $total_pages) { echo "<a href='?page=$total_pages'>В конец</a>"; }
Задача 2. Модифицируйте код так, чтобы при отсутствии записей выводилось сообщение «Данные не найдены».
Пример полного кода
<?php
// Подключение к базе данных
$conn = new mysqli("localhost", "root", "", "test_db");
// Получение общего количества записей
$result = $conn->query("SELECT COUNT(id) AS total FROM products");
$total_records = $result->fetch_assoc()['total'];
// Настройки пагинации
$records_per_page = 10;
$current_page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
$total_pages = ceil($total_records / $records_per_page);
// Корректировка текущей страницы
if ($current_page > $total_pages) {
$current_page = $total_pages;
}
// Запрос данных
$offset = ($current_page - 1) * $records_per_page;
$result = $conn->query("SELECT * FROM products LIMIT $records_per_page OFFSET $offset");
// Вывод данных
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "<div>{$row['name']}</div>";
}
} else {
echo "Данные не найдены.";
}
// Пагинация
echo "<div class='pagination'>";
if ($current_page > 1) {
echo "<a href='?page=1'>В начало</a>";
echo "<a href='?page=" . ($current_page - 1) . "'>Назад</a>";
}
for ($i = 1; $i <= $total_pages; $i++) {
$active = ($i == $current_page) ? " class='active'" : "";
echo "<a href='?page=$i'$active>$i</a>";
}
if ($current_page < $total_pages) {
echo "<a href='?page=" . ($current_page + 1) . "'>Вперед</a>";
echo "<a href='?page=$total_pages'>В конец</a>";
}
echo "</div>";
$conn->close();
?>
Попробуйте усложнить задачи:
- Добавьте AJAX-подгрузку данных без перезагрузки страницы.
- Реализуйте пагинацию с использованием паттерна MVC.
Не забывайте тестировать код при разных сценариях, когда записей нет, когда страница некорректная и т.д.
Полный курс с уроками по PHP для начинающих доступен здесь: https://max-gabov.ru/php-dlya-nachinaushih
Не стесняйтесь задавать вопросы в комментариях к курсу.