WP REST API – мощный инструмент для создания приложений на WordPress. Однако при работе с большими объёмами данных пагинация становится обязательной для удобства пользователя и оптимизации загрузки. В этой статье разберём, как добавить пагинацию в WP REST API с возможностью фильтрации и реализовать кеширование для повышения производительности.
Основы пагинации в WP REST API
По умолчанию WP REST API поддерживает базовую пагинацию через параметры per_page и page. Например, запрос к /wp-json/wp/v2/posts?per_page=5&page=2 вернёт вторую страницу с 5 постами.
Но что делать, если нужно добавить фильтры по меткам, таксономиям, произвольным полям и при этом сохранить корректную пагинацию? Для этого создадим собственный эндпоинт с расширенной логикой.
Создание кастомного REST API эндпоинта с пагинацией и фильтрами
Добавим в файл functions.php или в плагин следующий код для регистрации нового маршрута:
add_action('rest_api_init', function () {
register_rest_route('wppagenavi/v1', '/custom-posts', [
'methods' => 'GET',
'callback' => 'wppagenavi_get_custom_posts',
'args' => [
'page' => [
'validate_callback' => 'is_numeric',
'default' => 1
],
'per_page' => [
'validate_callback' => 'is_numeric',
'default' => 10
],
'category' => [
'validate_callback' => 'is_string',
'required' => false
],
'tag' => [
'validate_callback' => 'is_string',
'required' => false
],
],
]);
});
function wppagenavi_get_custom_posts(WP_REST_Request $request) {
$page = max(1, (int) $request->get_param('page'));
$per_page = min(100, max(1, (int) $request->get_param('per_page')));
$category = $request->get_param('category');
$tag = $request->get_param('tag');
$args = [
'post_type' => 'post',
'posts_per_page' => $per_page,
'paged' => $page,
'post_status' => 'publish',
];
if ($category) {
$args['category_name'] = sanitize_text_field($category);
}
if ($tag) {
$args['tag'] = sanitize_text_field($tag);
}
$query = new WP_Query($args);
$posts = [];
foreach ($query->posts as $post) {
$posts[] = [
'id' => $post->ID,
'title' => get_the_title($post),
'excerpt' => get_the_excerpt($post),
'date' => get_the_date('', $post),
'link' => get_permalink($post),
];
}
$total = (int) $query->found_posts;
$total_pages = (int) $query->max_num_pages;
return [
'page' => $page,
'per_page' => $per_page,
'total_items' => $total,
'total_pages' => $total_pages,
'posts' => $posts,
];
}
Этот эндпоинт позволяет делать запросы с параметрами page, per_page, category и tag. Он возвращает данные с учётом фильтров и пагинации.
Добавление кеширования для оптимизации производительности
При большом числе запросов к API полезно кешировать результаты. Для этого можно использовать объектный кеш WordPress или Transients API. Ниже пример кеширования результата запроса на 10 минут.
function wppagenavi_get_custom_posts(WP_REST_Request $request) {
$page = max(1, (int) $request->get_param('page'));
$per_page = min(100, max(1, (int) $request->get_param('per_page')));
$category = $request->get_param('category');
$tag = $request->get_param('tag');
$cache_key = 'wppagenavi_custom_posts_' . md5(json_encode([$page, $per_page, $category, $tag]));
$cached = get_transient($cache_key);
if ($cached !== false) {
return $cached;
}
$args = [
'post_type' => 'post',
'posts_per_page' => $per_page,
'paged' => $page,
'post_status' => 'publish',
];
if ($category) {
$args['category_name'] = sanitize_text_field($category);
}
if ($tag) {
$args['tag'] = sanitize_text_field($tag);
}
$query = new WP_Query($args);
$posts = [];
foreach ($query->posts as $post) {
$posts[] = [
'id' => $post->ID,
'title' => get_the_title($post),
'excerpt' => get_the_excerpt($post),
'date' => get_the_date('', $post),
'link' => get_permalink($post),
];
}
$result = [
'page' => $page,
'per_page' => $per_page,
'total_items' => (int) $query->found_posts,
'total_pages' => (int) $query->max_num_pages,
'posts' => $posts,
];
set_transient($cache_key, $result, 10 * MINUTE_IN_SECONDS);
return $result;
}
Использование кеша снизит нагрузку на базу данных при повторных запросах с одинаковыми параметрами.
Как использовать созданный эндпоинт на фронтенде
Пример запроса с помощью fetch на JavaScript с выводом результата в консоль:
fetch('/wp-json/wppagenavi/v1/custom-posts?page=1&per_page=5&category=news')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Вы можете использовать полученные данные для построения пагинации и отображения списка постов с фильтрами.
Рекомендации по улучшению и расширению
- Добавьте параметры для фильтрации по произвольным полям (meta_query).
- Реализуйте сортировку (orderby и order) через параметры API.
- Используйте WP_Query с кешированием на уровне объекта для ещё более быстрой работы.
- Подключите пагинацию к вашим Vue.js или React-приложениям для динамического вывода контента.
- Если хотите использовать готовые решения, обратите внимание на плагин WP-PageNavi, который поможет с визуальной навигацией, однако для REST API нужен кастомный код, как показано выше.