Методы расчета страниц в PHP: от простых до продвинутых

Раздел: PHP веб-разработка -> подсчет страниц

Подсчет числа страниц в PHP: практические решения

Основной способ вычисления количества страниц

Для постраничного вывода данных чаще всего используется простая формула: общее количество записей делится на количество записей на одной странице, а результат округляется вверх до целого числа. Это гарантирует, что для оставшихся записей будет создана дополнительная страница.


<?php
$totalItems = 150;    // общее число записей
$perPage = 20;         // записей на страницу
$totalPages = (int)ceil($totalItems / $perPage); // 8
echo $totalPages; // 8
?>
  

Php сколько страниц (количество страниц php)

8

Функция ceil() поднимает дробное значение до ближайшего целого вверх. Если бы использовалось обычное деление без округления, результат был бы 7.5, и страница 8 пропала бы.

Типичные ошибки: забыть проверить $totalItems на ноль. Если записей нет, ceil(0 / 20) вернёт 0, что корректно, но некоторые разработчики вручную присваивают 1, создавая пустую страницу. Решение – использовать $totalPages = max(1, (int)ceil($totalItems / $perPage)); если нужно гарантировать хотя бы одну страницу.

Другая ошибка: деление на ноль при $perPage = 0. Обязательно проверять или использовать $perPage > 0.

Случаи применения:

  • Любая постраничная навигация (списки товаров, статьи, комментарии).
  • Вычисление количества страниц для отчётов или экспорта данных.
  • Динамическое построение URL вида /page/{N}.

Как обработать случай, когда общее количество записей равно нулю?

Если записей нет, можно отобразить сообщение об отсутствии данных, а пагинацию скрыть. При этом $totalPages должен быть равен 0 или 1? Выбор зависит от логики интерфейса. Пример проверки:


<?php
$totalPages = 0;
if ($totalItems > 0) {
    $totalPages = (int)ceil($totalItems / $perPage);
}
?>
  

В шаблоне можно вывести «Нет записей», если $totalPages === 0.

Проблема: некоторые ORM возвращают 0 для COUNT, даже если таблица пуста. Это нормально. Важно не принудительно устанавливать $totalPages = 1 при нулевых данных – это создаст пустую страницу, что дезориентирует пользователя.

Как подсчитать страницы, используя SQL запрос с COUNT?

Классический подход – сначала получить общее количество записей через COUNT(*), затем применить формулу. Это универсально для любых СУБД.


<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->query('SELECT COUNT(*) FROM products');
$totalItems = (int)$stmt->fetchColumn();
$perPage = 10;
$totalPages = (int)ceil($totalItems / $perPage);
echo $totalPages;
?>
  
15 (при 150 записях)

Для пагинации с условиями (например, категория) используйте параметризованный запрос:


<?php
$categoryId = 5;
$stmt = $pdo->prepare('SELECT COUNT(*) FROM products WHERE category_id = ?');
$stmt->execute([$categoryId]);
$totalItems = (int)$stmt->fetchColumn();
?>
  

Типичная ошибка: выполнять SELECT COUNT(*) на каждой странице без кеширования. Для больших таблиц это создаёт лишнюю нагрузку. Решение – кешировать результат на короткое время (например, через Memcached или Redis).

Как вычислить число страниц, если навигация строится по смещению (OFFSET) и лимиту?

Часто в SQL используется LIMIT $perPage OFFSET $offset. Количество страниц при этом рассчитывается так же, но $offset = ($currentPage - 1) * $perPage. Важно проверять, чтобы номер текущей страницы не превышал общее количество страниц.


<?php
$totalItems = 285;
$perPage = 25;
$totalPages = (int)ceil($totalItems / $perPage); // 12
$currentPage = min($_GET['page'] ?? 1, $totalPages);
$offset = ($currentPage - 1) * $perPage;
echo "Страница $currentPage из $totalPages, смещение: $offset";
?>
  
Страница 1 из 12, смещение: 0

Проблема: если входной параметр page меньше 1 или нечисловой, возможно возникновение ошибок. Решение – приводить к целому и ограничивать диапазоном от 1 до $totalPages.

Как рассчитать количество страниц для пагинации с динамическим изменением размера страницы?

Иногда пользователь может выбрать количество записей на странице (10, 20, 50). Тогда $perPage – переменная, и общее число страниц пересчитывается.


<?php
$totalItems = 200;
$perPage = (int)($_GET['per_page'] ?? 20);
$allowed = [10, 20, 50];
if (!in_array($perPage, $allowed)) $perPage = 20;
$totalPages = (int)ceil($totalItems / $perPage);
echo $totalPages;
?>
  
10 (если выбрано 20), 20 (если 10), 4 (если 50)

Ошибка: не проверять допустимые значения $perPage. Пользователь может передать 0 или отрицательное число – это приведёт к делению на ноль или некорректному результату. Решение – явно задать список разрешённых значений и использовать значение по умолчанию.

Расширенные примеры подсчёта страниц в PHP

Пример 1: Класс для пагинации с кешированием общего числа записей

Пример

<?php
class Paginator {
    private int $totalItems;
    private int $perPage;
    private int $totalPages;
    private $cache;

    public function __construct(int $totalItems, int $perPage, $cache = null) {
        $this->totalItems = $totalItems;
        $this->perPage = $perPage;
        $this->cache = $cache;
        $this->totalPages = $this->calculatePages();
    }

    private function calculatePages(): int {
        if ($this->perPage <= 0) {
            throw new InvalidArgumentException("perPage must be positive");
        }
        return (int)ceil($this->totalItems / $this->perPage);
    }

    public function getPages(): int {
        return $this->totalPages;
    }

    public function getOffset(int $currentPage): int {
        $page = max(1, min($currentPage, $this->totalPages));
        return ($page - 1) * $this->perPage;
    }

    public function getPageNumbers(int $range = 2): array {
        // Возвращает номера страниц для отображения с многоточием
        $pages = [];
        $total = $this->totalPages;
        for ($i = 1; $i <= $total; $i++) {
            if ($i == 1 || $i == $total || abs($i - $total) <= $range || abs($i - 1) <= $range) {
                $pages[] = $i;
            } elseif (end($pages) !== '...') {
                $pages[] = '...';
            }
        }
        return $pages;
    }
}

// Использование
$items = 500;
$perPage = 20;
$paginator = new Paginator($items, $perPage);
echo $paginator->getPages(); // 25
?>
25

Пример 2: Подсчёт страниц в результатах поиска с фильтрами (использование подзапроса)

Пример

<?php
$search = 'ноутбук';
$stmt = $pdo->prepare("
    SELECT COUNT(*)
    FROM products
    WHERE MATCH(name, description) AGAINST(:search IN BOOLEAN MODE)
");
$stmt->execute([':search' => $search]);
$totalItems = (int)$stmt->fetchColumn();
$perPage = 15;
$totalPages = (int)ceil($totalItems / $perPage);
echo "Найдено $totalItems товаров, страниц: $totalPages";
?>
Найдено 123 товаров, страниц: 9

Пример 3: Вычисление числа страниц с кешированием в Redis

Пример

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$perPage = 20;
$cacheKey = 'total_items:products';

$totalItems = $redis->get($cacheKey);
if ($totalItems === false) {
    $stmt = $pdo->query('SELECT COUNT(*) FROM products');
    $totalItems = (int)$stmt->fetchColumn();
    $redis->setex($cacheKey, 300, $totalItems); // кеш на 5 минут
}
$totalPages = (int)ceil($totalItems / $perPage);
echo $totalPages;
?>
85 (при 1700 записях)

Пример 4: Пагинация с AJAX и динамическим обновлением панели страниц

Пример

<?php
// server.php – возвращает JSON с данными и числом страниц
$page = (int)($_GET['page'] ?? 1);
$perPage = 10;
$stmt = $pdo->query('SELECT COUNT(*) FROM comments');
$totalItems = (int)$stmt->fetchColumn();
$totalPages = (int)ceil($totalItems / $perPage);

$stmt = $pdo->prepare('SELECT * FROM comments LIMIT ? OFFSET ?');
$stmt->execute([$perPage, ($page-1)*$perPage]);
$comments = $stmt->fetchAll();

echo json_encode([
    'totalPages' => $totalPages,
    'currentPage' => $page,
    'comments' => $comments
]);
?>
{"totalPages":23,"currentPage":1,"comments":[...]}

Пример 5: Обработка дробных значений и корректировка при нестандартном лимите

Пример

<?php
$items = 0;
$perPage = 15;
$totalPages = $items > 0 ? (int)ceil($items / $perPage) : 0;
echo $totalPages; // 0

$items = 1;
$totalPages = (int)ceil($items / $perPage); // 1

$items = 14;
$totalPages = (int)ceil($items / $perPage); // 1 (14/15=0.93, ceil=1)

$items = 15;
$totalPages = (int)ceil($items / $perPage); // 1

$items = 16;
$totalPages = (int)ceil($items / $perPage); // 2
?>
0, 1, 1, 1, 2

Обратите внимание: для одной записи и лимита в 15 страница одна, что логично. При нуле записей возвращается 0 – это позволяет скрыть пагинацию.

количество страниц PHP - comments

En
Php сколько страниц (php)