Как реализовать кастомную пагинацию в REST API WordPress
Когда вы работаете с REST API WordPress, встроенная пагинация часто может не покрывать все ваши потребности. Особенно это актуально, если вы создаёте кастомные эндпоинты и хотите гибко управлять выводом данных. В этой статье мы подробно рассмотрим, как реализовать кастомную пагинацию для REST API в WordPress, чтобы максимально эффективно выдавать данные клиенту, избегать проблем с производительностью и обеспечивать удобство использования.
Почему стандартная пагинация REST API WordPress не всегда подходит
По умолчанию WordPress REST API реализует пагинацию через параметры page и per_page. Это работает для большинства сценариев, но при работе с большими объемами данных или сложными запросами могут возникать проблемы:
- Ограничение параметра
per_pageмаксимальным значением 100. - Отсутствие поддержки нестандартных фильтров и сортировок вместе с пагинацией.
- Нет возможности возвращать дополнительную информацию о страницах (например, количество страниц, общее число записей).
Для кастомных эндпоинтов и сложных бизнес-логик нужна более гибкая пагинация, которую мы и реализуем в этой статье.
План реализации кастомной пагинации в WPAPI REST API
Основные шаги, которые мы рассмотрим:
- Создание кастомного REST API эндпоинта.
- Обработка параметров пагинации:
pageиper_pageс валидацией. - Запрос данных с использованием
WP_Queryс учетом пагинации. - Формирование ответа с дополнительными метаданными: общее количество записей, количество страниц и текущая страница.
- Добавление заголовков 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 помогает интеграциям правильно отображать и использовать данные.
Пример кода, приведённый в статье, можно адаптировать под ваши кастомные типы постов и бизнес-логику. Не забывайте о безопасности и валидации параметров, а также о контроле нагрузки на сервер.