Как реализовать кастомную пагинацию в REST API WordPress

Когда вы работаете с REST API WordPress, встроенная пагинация часто может не покрывать все ваши потребности. Особенно это актуально, если вы создаёте кастомные эндпоинты и хотите гибко управлять выводом данных. В этой статье мы подробно рассмотрим, как реализовать кастомную пагинацию для REST API в WordPress, чтобы максимально эффективно выдавать данные клиенту, избегать проблем с производительностью и обеспечивать удобство использования.

Почему стандартная пагинация REST API WordPress не всегда подходит

По умолчанию WordPress REST API реализует пагинацию через параметры page и per_page. Это работает для большинства сценариев, но при работе с большими объемами данных или сложными запросами могут возникать проблемы:

  • Ограничение параметра per_page максимальным значением 100.
  • Отсутствие поддержки нестандартных фильтров и сортировок вместе с пагинацией.
  • Нет возможности возвращать дополнительную информацию о страницах (например, количество страниц, общее число записей).

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

План реализации кастомной пагинации в WPAPI REST API

Основные шаги, которые мы рассмотрим:

  1. Создание кастомного REST API эндпоинта.
  2. Обработка параметров пагинации: page и per_page с валидацией.
  3. Запрос данных с использованием WP_Query с учетом пагинации.
  4. Формирование ответа с дополнительными метаданными: общее количество записей, количество страниц и текущая страница.
  5. Добавление заголовков HTTP для пагинации.

Создаём кастомный REST API эндпоинт с пагинацией

Вначале зарегистрируем новый маршрут в REST API. Ключевая функция будет называться wpapi_register_custom_paginated_endpoint. Она создаст эндпоинт /wpapi/v1/items, который вернёт список кастомных записей с пагинацией.

add_action('rest_api_init', 'wpapi_register_custom_paginated_endpoint');
function wpapi_register_custom_paginated_endpoint() {
    register_rest_route('wpapi/v1', '/items', [
        'methods' => 'GET',
        'callback' => 'wpapi_get_paginated_items',
        'args' => [
            'page' => [
                'validate_callback' => 'is_numeric',
                'default' => 1
            ],
            'per_page' => [
                'validate_callback' => 'is_numeric',
                'default' => 10
            ],
        ],
        'permission_callback' => '__return_true',
    ]);
}

Здесь мы определили параметры запроса page и per_page с валидацией и значениями по умолчанию.

Обработка параметров и выполнение запроса WP_Query с пагинацией

Далее реализуем функцию wpapi_get_paginated_items, которая будет извлекать данные с учётом пагинации и формировать ответ.

function wpapi_get_paginated_items(WP_REST_Request $request) {
    $page = max(1, (int) $request->get_param('page'));
    $per_page = (int) $request->get_param('per_page');
    $per_page = ($per_page > 0 && $per_page <= 100) ? $per_page : 10;

    $args = [
        'post_type' => 'post', // Можно заменить на кастомный тип
        'posts_per_page' => $per_page,
        'paged' => $page,
        'post_status' => 'publish',
    ];

    $query = new WP_Query($args);

    $total_posts = $query->found_posts;
    $total_pages = $query->max_num_pages;

    $items = [];
    while ($query->have_posts()) {
        $query->the_post();
        $items[] = [
            'id' => get_the_ID(),
            'title' => get_the_title(),
            'link' => get_permalink(),
        ];
    }
    wp_reset_postdata();

    // Формируем ответ
    $response = new WP_REST_Response($items);
    $response->header('X-WP-Total', (int) $total_posts);
    $response->header('X-WP-TotalPages', (int) $total_pages);

    return $response;
}

Основные моменты:

  • Параметры page и per_page корректируются, чтобы избежать ошибок и ограничений.
  • Используется WP_Query для выборки постов с учётом пагинации.
  • В массиве $items формируем упрощённый набор данных с id, заголовком и ссылкой.
  • В заголовках HTTP добавляем X-WP-Total (общее число записей) и X-WP-TotalPages (число страниц), что полезно для клиента.

Расширение пагинации: сортировка и фильтрация

Часто требуется не просто пагинация, но и возможность фильтровать и сортировать данные. Рассмотрим, как добавить поддержку параметров сортировки и фильтров в наш эндпоинт.

Добавим в register_rest_route новые аргументы:

'args' => [
    'page' => [
        'validate_callback' => 'is_numeric',
        'default' => 1
    ],
    'per_page' => [
        'validate_callback' => 'is_numeric',
        'default' => 10
    ],
    'orderby' => [
        'validate_callback' => function($param, $request, $key) {
            $allowed = ['date', 'title', 'modified'];
            return in_array($param, $allowed, true);
        },
        'default' => 'date'
    ],
    'order' => [
        'validate_callback' => function($param, $request, $key) {
            return in_array(strtoupper($param), ['ASC', 'DESC'], true);
        },
        'default' => 'DESC'
    ],
    'category' => [
        'validate_callback' => 'is_numeric',
        'required' => false
    ],
],

В функции wpapi_get_paginated_items добавим обработку параметров:

$orderby = $request->get_param('orderby');
$order = strtoupper($request->get_param('order')) === 'ASC' ? 'ASC' : 'DESC';

$args['orderby'] = $orderby;
$args['order'] = $order;

$category = $request->get_param('category');
if ($category) {
    $args['cat'] = (int) $category;
}

Таким образом, клиент может вызвать эндпоинт с параметрами:

/wp-json/wpapi/v1/items?page=2&per_page=5&orderby=title&order=ASC&category=10
<

И получить отсортированный и отфильтрованный список постов с пагинацией.

Практические рекомендации по производительности

Пагинация в REST API может создавать нагрузку, особенно при больших объёмах данных. Вот несколько советов для оптимизации:

  • Используйте индексы в базе данных для важных полей (например, даты публикации).
  • Ограничивайте максимальное значение per_page (не больше 100), чтобы избежать тяжелых запросов.
  • Кешируйте результаты с помощью Transients API или внешних кешей (Redis, Memcached).
  • Если нужно работать с очень большим количеством данных, рассмотрите асинхронную загрузку и lazy load на клиенте.

Выводы

Реализация кастомной пагинации в WordPress REST API — это важный шаг к созданию гибких и производительных API для ваших проектов. Используя параметры page и per_page вместе с дополнительными фильтрами и сортировками, вы обеспечите удобство для разработчиков фронтенда и клиентов API. Кроме того, добавление метаданных и заголовков HTTP помогает интеграциям правильно отображать и использовать данные.

Пример кода, приведённый в статье, можно адаптировать под ваши кастомные типы постов и бизнес-логику. Не забывайте о безопасности и валидации параметров, а также о контроле нагрузки на сервер.

Шаблоны для WP Плагины для WP