WP REST API пагинация с кастомными метаданными
Пагинация — одна из ключевых задач при работе с REST API в WordPress, особенно если необходимо выводить данные с учетом пользовательских метаданных. В стандартных эндпоинтах WordPress пагинация работает по параметрам page и per_page, однако при фильтрации или сортировке по кастомным полям это часто становится проблемой. В этой статье разберем, как реализовать эффективную пагинацию в WP REST API с учетом пользовательских метаданных, используя примеры кода и лучшие практики.
Почему стандартная пагинация WP REST API не всегда подходит
Стандартные REST API эндпоинты, например /wp/v2/posts, поддерживают пагинацию по параметрам page и per_page. Однако если необходимо фильтровать записи по метаданным, например, вывести товары с определенным значением поля price или посты с кастомным статусом, то стандартный механизм пагинации может не работать корректно, так как WP_Query с мета-запросами требует особой обработки.
Без правильной обработки пагинация может показывать некорректное количество страниц, повторяющиеся записи или вовсе пропускать данные. Поэтому нужно создавать кастомные REST API эндпоинты с поддержкой пагинации и фильтрации.
Создаем кастомный REST API эндпоинт с пагинацией и мета-запросами
Для начала зарегистрируем новый эндпоинт, который будет возвращать посты с фильтрацией по метаданным и поддержкой пагинации.
add_action('rest_api_init', function () {
register_rest_route('wpapi/v1', '/custom-posts', [
'methods' => 'GET',
'callback' => 'wpapi_get_custom_posts',
'permission_callback' => '__return_true',
'args' => [
'page' => [
'validate_callback' => 'is_numeric',
'default' => 1,
],
'per_page' => [
'validate_callback' => 'is_numeric',
'default' => 10,
],
'meta_key' => [
'validate_callback' => 'is_string',
],
'meta_value' => [
'validate_callback' => 'is_string',
],
],
]);
});
function wpapi_get_custom_posts($request) {
$page = (int)$request->get_param('page');
$per_page = (int)$request->get_param('per_page');
$meta_key = $request->get_param('meta_key');
$meta_value = $request->get_param('meta_value');
$args = [
'post_type' => 'post',
'posts_per_page' => $per_page,
'paged' => $page,
];
if ($meta_key && $meta_value) {
$args['meta_query'] = [
[
'key' => $meta_key,
'value' => $meta_value,
'compare' => '=',
],
];
}
$query = new WP_Query($args);
$posts = [];
foreach ($query->posts as $post) {
$posts[] = [
'id' => $post->ID,
'title' => get_the_title($post),
'date' => $post->post_date,
'meta' => get_post_meta($post->ID),
];
}
$total_posts = (int)$query->found_posts;
$total_pages = (int)$query->max_num_pages;
$response = new WP_REST_Response($posts, 200);
$response->header('X-WP-Total', $total_posts);
$response->header('X-WP-TotalPages', $total_pages);
return $response;
}В этом коде мы регистрируем эндпоинт /wpapi/v1/custom-posts с параметрами для пагинации и фильтрации по метаданным. В ответе передаем заголовки X-WP-Total и X-WP-TotalPages, чтобы клиент понимал общее количество записей и страниц.
Обработка пагинации на стороне клиента
При использовании этого API на фронтенде можно получать данные постранично, передавая параметры page и per_page. Пример запроса:
https://example.com/wp-json/wpapi/v1/custom-posts?page=2&per_page=5&meta_key=color&meta_value=redТак вы получите вторую страницу постов, у которых метаполе color равно red. В ответе будет не более 5 записей и заголовки с общей статистикой.
Оптимизация запросов и кеширование результатов
Фильтрация по метаданным может быть ресурсоёмкой, особенно на больших базах данных. Чтобы улучшить производительность, рекомендуем:
- Использовать индексы для мета-таблиц через запрос к базе данных.
- Кешировать результаты с помощью Transients API или внешних кеш-систем.
- Ограничивать максимальное значение
per_page, чтобы не отдавать слишком большие объемы данных.
Пример кеширования результата запроса в функции обработчика:
function wpapi_get_custom_posts($request) {
$page = (int)$request->get_param('page');
$per_page = (int)$request->get_param('per_page');
$meta_key = $request->get_param('meta_key');
$meta_value = $request->get_param('meta_value');
$cache_key = 'wpapi_custom_posts_' . md5(serialize([$page, $per_page, $meta_key, $meta_value]));
$cached = get_transient($cache_key);
if ($cached !== false) {
return new WP_REST_Response($cached['posts'], 200, [
'X-WP-Total' => $cached['total_posts'],
'X-WP-TotalPages' => $cached['total_pages'],
]);
}
// ... здесь WP_Query как выше ...
set_transient($cache_key, [
'posts' => $posts,
'total_posts' => $total_posts,
'total_pages' => $total_pages,
], 5 * MINUTE_IN_SECONDS);
return $response;
}Используем плагины для расширения возможностей REST API
Для удобства можно использовать готовые решения из репозитория:
- Clearfy Pro — для оптимизации запросов и кеширования.
- WPRemark — удобный инструмент для расширения REST API, добавления новых полей и фильтров.
Они помогут уменьшить нагрузку и расширить функционал без необходимости писать весь код вручную.
Ошибки и отладка при работе с пагинацией и метаданными
Частые ошибки при реализации пагинации с мета-запросами:
- Неправильное использование параметров
pagedиposts_per_pageв WP_Query. - Отсутствие передачи заголовков
X-WP-TotalиX-WP-TotalPagesв ответе, из-за чего клиент не понимает, сколько страниц всего. - Перекрытие фильтров и хуков, которые влияют на WP_Query в других частях сайта.
Для отладки используйте WP_DEBUG и функцию error_log(). Также можно временно выводить SQL-запросы с помощью плагина Query Monitor.