WP REST API: выполнение длинного запроса с пагинацией и фильтрами

При работе с 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.

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