При работе с WordPress REST API часто возникает задача получить большой объем данных с возможностью фильтрации и пагинации. Это особенно важно, если вы разрабатываете фронтенд-приложение или интеграцию, где нужно эффективно обрабатывать запросы и не перегружать сервер. В этой статье разберем, как реализовать выполнение длинного запроса к REST API с пагинацией и возможностью фильтрации данных, а также приведем примеры кода для создания кастомного эндпоинта на базе WP API.
Почему важна пагинация и фильтры в REST API WordPress
По умолчанию REST API WordPress возвращает ограниченное число записей (обычно 10) при запросе к стандартным эндпоинтам, например, к /wp/v2/posts. Это сделано для оптимизации производительности и снижения нагрузки на сервер. Однако, если необходимо получить больше данных, например, для построения сложного интерфейса, нужно работать с пагинацией и фильтрами.
Без пагинации при запросе большого количества записей можно столкнуться с проблемами:
- Высокая нагрузка на сервер
- Длительное время ответа API
- Плохая отзывчивость интерфейса
Фильтры позволяют ограничить выборку данных по нужным параметрам, например, по дате, категории или пользовательским полям. Это делает API более гибким и удобным.
Как устроена пагинация в WP REST API
Стандартная пагинация в WP REST API реализована через параметры per_page и page:
per_page— количество элементов на странице (максимум 100)page— номер страницы, начиная с 1
Например, запрос /wp-json/wp/v2/posts?per_page=20&page=2 вернет вторую страницу из 20 записей.
Сервер в заголовках ответа возвращает дополнительные данные для навигации:
X-WP-Total— общее количество записейX-WP-TotalPages— количество страниц
Это позволяет клиенту строить интерфейс пагинации.
Добавление кастомных фильтров в REST API
Для расширения стандартных фильтров можно создавать кастомные параметры запроса. Рассмотрим, как добавить фильтр по произвольному полю (метаполю) с помощью хука rest_post_query.
add_filter('rest_post_query', 'wpapi_rest_post_query_filter', 10, 2);
function wpapi_rest_post_query_filter($args, $request) {
if (!empty($request['custom_meta_key'])) {
$args['meta_query'] = [
[
'key' => 'custom_meta_key',
'value' => sanitize_text_field($request['custom_meta_key']),
'compare' => '='
]
];
}
return $args;
}
Теперь при запросе /wp-json/wp/v2/posts?custom_meta_key=значение будут возвращаться посты с заданным метаполем.
Создание кастомного эндпоинта с пагинацией и фильтрами
Иногда стандартных эндпоинтов недостаточно, и нужно сделать собственный, чтобы полностью контролировать логику выборки данных. Ниже пример регистрации кастомного REST API эндпоинта, который поддерживает пагинацию и фильтрацию по категории и произвольному полю.
add_action('rest_api_init', function () {
register_rest_route('wpapi/v1', '/custom-posts', [
'methods' => 'GET',
'callback' => 'wpapi_custom_posts_callback',
'args' => [
'page' => [
'validate_callback' => 'is_numeric',
'default' => 1,
],
'per_page' => [
'validate_callback' => 'is_numeric',
'default' => 10,
],
'category' => [
'validate_callback' => 'is_numeric',
],
'custom_meta_key' => [
'sanitize_callback' => 'sanitize_text_field',
],
],
]);
});
function wpapi_custom_posts_callback(WP_REST_Request $request) {
$page = (int) $request->get_param('page');
$per_page = (int) $request->get_param('per_page');
$category = $request->get_param('category');
$custom_meta_key = $request->get_param('custom_meta_key');
$args = [
'post_type' => 'post',
'posts_per_page' => $per_page,
'paged' => $page,
];
if ($category) {
$args['cat'] = $category;
}
if ($custom_meta_key) {
$args['meta_query'] = [
[
'key' => 'custom_meta_key',
'value' => $custom_meta_key,
'compare' => '=',
]
];
}
$query = new WP_Query($args);
$posts = [];
foreach ($query->posts as $post) {
$posts[] = [
'id' => $post->ID,
'title' => get_the_title($post),
'date' => get_the_date('', $post),
'link' => get_permalink($post),
];
}
return [
'posts' => $posts,
'total' => (int) $query->found_posts,
'total_pages' => (int) $query->max_num_pages,
'current_page' => $page,
];
}
Этот эндпоинт доступен по адресу /wp-json/wpapi/v1/custom-posts. Параметры:
page— номер страницыper_page— количество записей на страницуcategory— ID категории для фильтраcustom_meta_key— значение пользовательского метаполя
Кэширование результатов REST API для повышения производительности
При больших объемах данных и частых запросах имеет смысл кэшировать результаты. Для этого можно использовать transient API WordPress или плагины кэширования.
Пример кэширования ответа нашего кастомного эндпоинта:
function wpapi_custom_posts_callback(WP_REST_Request $request) {
$cache_key = 'wpapi_custom_posts_' . md5(json_encode($request->get_params()));
$cached = get_transient($cache_key);
if ($cached !== false) {
return $cached;
}
// ... код выборки данных (как выше) ...
$response = [
'posts' => $posts,
'total' => (int) $query->found_posts,
'total_pages' => (int) $query->max_num_pages,
'current_page' => $page,
];
set_transient($cache_key, $response, HOUR_IN_SECONDS);
return $response;
}
Это значительно снизит нагрузку при многократных одинаковых запросах.
Рекомендации по безопасности и ограничениям
При добавлении фильтров и пагинации важно валидировать и санитизировать входные параметры, чтобы избежать SQL-инъекций и других уязвимостей. В примерах выше для этого используются функции sanitize_text_field и проверка типа параметров.
Также стоит ограничивать максимальное значение per_page (например, до 50 или 100) для предотвращения чрезмерной нагрузки.
Плагины для удобной работы с REST API и пагинацией
Для расширенной работы с REST API можно использовать плагины:
- Clearfy Pro — ускоряет работу сайта и оптимизирует REST API, в том числе кэширование и ограничения
- ABC Pagination — расширенные возможности пагинации для фронтенда и API
Эти инструменты помогут улучшить производительность и функциональность вашего REST API.