WordPress REST: разработка API эндпоинтов

Разработка кастомных REST API эндпоинтов WordPress — наша специализация уже 5+ лет. Мобильное приложение SPA-фронтенда требует от WordPress агрегированных данных с фильтрацией по таксономиям и метаполям. Стандартный `/wp/v2/posts` не умеет выдавать сумму заказов клиента за период или список проектов

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
WordPress REST: разработка API эндпоинтов
Средний
~2-3 дня

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1414
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1285
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    980
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1240
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    982
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    994

Разработка кастомных REST API эндпоинтов WordPress — наша специализация уже 5+ лет. Мобильное приложение SPA-фронтенда требует от WordPress агрегированных данных с фильтрацией по таксономиям и метаполям. Стандартный /wp/v2/posts не умеет выдавать сумму заказов клиента за период или список проектов с комбинированной сортировкой. Типичная ситуация: без кеширования при 5 000 запросов в час сервер падает. Разработчики часто лепят прямые SQL-запросы, получая N+1 проблем и уязвимости. Наш опыт показал: правильно спроектированный кастомный эндпоинт решает эти задачи за 2–5 дней, снижая нагрузку на базу в 3–5 раз. В этой статье разберём типовые сценарии, стек и архитектуру.

Чтобы избежать таких проблем, мы используем единый интерфейс для всех данных: кастомный REST API эндпоинт агрегирует записи, метаполя и таксономии за один запрос. Это сокращает количество HTTP-вызовов в 5–10 раз и упрощает поддержку фронтенда. Например, для одного из проектов (каталог с 20 000 товаров) мы реализовали эндпоинт /my-plugin/v1/products с фильтрацией по категориям, цене и характеристикам — время ответа сократилось с 4 до 1 секунды.

Ограничения стандартного REST API WordPress

Стандартные маршруты /wp/v2/posts и /wp/v2/pages хороши для чтения записей, но не для:

  • Агрегированных данных — сумма заказов клиента за последний месяц.
  • Сложных фильтров — комбинация метаполей и таксономий с сортировкой.
  • Кастомных операций — создание заказа с проверкой стока и отправкой email.

Без кастомного эндпоинта клиенту приходится делать несколько запросов или использовать небезопасные SQL-запросы. Кастомный эндпоинт с кешированием позволяет сократить время ответа с 4 до 1 секунды.

Регистрация кастомного REST API эндпоинта

Регистрация эндпоинта с GET и POST методами. Подробнее в REST API Handbook.

add_action('rest_api_init', function () { register_rest_route('my-plugin/v1', '/projects', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => 'my_plugin_get_projects', 'permission_callback' => '__return_true', 'args' => [ 'category' => [ 'type' => 'string', 'sanitize_callback' => 'sanitize_title', ], 'tech' => [ 'type' => 'array', 'items' => ['type' => 'string'], 'sanitize_callback' => function ($value) { return array_map('sanitize_title', (array) $value); }, ], 'per_page' => [ 'type' => 'integer', 'default' => 12, 'minimum' => 1, 'maximum' => 100, 'sanitize_callback' => 'absint', ], 'page' => [ 'type' => 'integer', 'default' => 1, 'minimum' => 1, 'sanitize_callback' => 'absint', ], ], ], [ 'methods' => WP_REST_Server::CREATABLE, 'callback' => 'my_plugin_create_project', 'permission_callback' => function () { return current_user_can('edit_posts'); }, ], ]); register_rest_route('my-plugin/v1', '/projects/(?P<id>\d+)', [ 'methods' => WP_REST_Server::READABLE, 'callback' => 'my_plugin_get_project', 'permission_callback' => '__return_true', 'args' => [ 'id' => [ 'validate_callback' => function ($param) { return is_numeric($param) && $param > 0; }, ], ], ]); }); 

Обработчик GET-запроса с фильтрацией по таксономиям:

function my_plugin_get_projects(WP_REST_Request $request): WP_REST_Response|WP_Error { $per_page = $request->get_param('per_page'); $page = $request->get_param('page'); $category = $request->get_param('category'); $techs = $request->get_param('tech'); $query_args = [ 'post_type' => 'project', 'post_status' => 'publish', 'posts_per_page' => $per_page, 'paged' => $page, 'no_found_rows' => false, ]; $tax_queries = []; if ($category) { $tax_queries[] = [ 'taxonomy' => 'project_category', 'field' => 'slug', 'terms' => $category, ]; } if (!empty($techs)) { $tax_queries[] = [ 'taxonomy' => 'tech_stack', 'field' => 'slug', 'terms' => $techs, 'operator' => 'IN', ]; } if (!empty($tax_queries)) { $query_args['tax_query'] = array_merge(['relation' => 'AND'], $tax_queries); } $query = new WP_Query($query_args); $projects = []; foreach ($query->posts as $post) { $projects[] = my_plugin_format_project($post); } $response = new WP_REST_Response($projects, 200); $response->header('X-WP-Total', $query->found_posts); $response->header('X-WP-TotalPages', $query->max_num_pages); return $response; } function my_plugin_format_project(WP_Post $post): array { $thumbnail_id = get_post_thumbnail_id($post->ID); $thumbnail_url = $thumbnail_id ? wp_get_attachment_image_url($thumbnail_id, 'large') : null; return [ 'id' => $post->ID, 'slug' => $post->post_name, 'title' => wp_strip_all_tags($post->post_title), 'excerpt' => wp_strip_all_tags(get_the_excerpt($post)), 'url' => get_permalink($post->ID), 'thumbnail' => $thumbnail_url, 'client' => get_post_meta($post->ID, 'project_client', true), 'year' => (int) get_post_meta($post->ID, 'project_year', true), 'categories' => wp_get_post_terms($post->ID, 'project_category', ['fields' => 'slugs']), 'tech_stack' => wp_get_post_terms($post->ID, 'tech_stack', ['fields' => 'slugs']), 'modified' => get_post_modified_time('c', true, $post), ]; } 

Обработчик POST с валидацией:

function my_plugin_create_project(WP_REST_Request $request): WP_REST_Response|WP_Error { $body = $request->get_json_params(); if (empty($body['title'])) { return new WP_Error('missing_title', 'Заголовок обязателен', ['status' => 422]); } $post_id = wp_insert_post([ 'post_type' => 'project', 'post_title' => sanitize_text_field($body['title']), 'post_content' => wp_kses_post($body['content'] ?? ''), 'post_status' => 'draft', 'post_author' => get_current_user_id(), ], true); if (is_wp_error($post_id)) { return new WP_Error('insert_failed', $post_id->get_error_message(), ['status' => 500]); } if (!empty($body['client'])) { update_post_meta($post_id, 'project_client', sanitize_text_field($body['client'])); } return new WP_REST_Response( ['id' => $post_id, 'url' => get_permalink($post_id)], 201 ); } 

Какой метод аутентификации выбрать?

Для GET-эндпоинтов достаточно публичного доступа. Для создания/изменения данных нужна проверка прав. Сравним методы:

Метод Сценарий Сложность
Cookie Запросы из админки Нулевая (встроен)
Application Passwords Внешние серверные клиенты Низкая (официальный плагин)
JWT SPA, мобильные приложения Средняя (плагин или самописный код)

Пример перехвата Bearer-токена:

add_filter('rest_authentication_errors', function ($result) { if (!empty($result)) return $result; $auth_header = $_SERVER['HTTP_AUTHORIZATION'] ?? ''; if (!str_starts_with($auth_header, 'Bearer ')) { return $result; } $token = substr($auth_header, 7); $user_id = my_plugin_validate_jwt($token); if (is_wp_error($user_id)) { return $user_id; } wp_set_current_user($user_id); return true; }); 

Кеширование ответов REST API

Для тяжёлых запросов используем Transients API. Это снижает нагрузку на БД в 3–5 раз. Пример:

function my_plugin_get_projects(WP_REST_Request $request): WP_REST_Response { $cache_key = 'projects_' . md5(serialize($request->get_params())); $cached = get_transient($cache_key); if ($cached !== false) { $response = new WP_REST_Response($cached['data'], 200); $response->header('X-WP-Total', $cached['total']); $response->header('X-Cache', 'HIT'); return $response; } // ... основная логика ... set_transient($cache_key, ['data' => $projects, 'total' => $total], 5 * MINUTE_IN_SECONDS); return $response; } add_action('save_post_project', function (int $post_id): void { global $wpdb; $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_projects_%'"); }); 

Что входит в разработку эндпоинтов

Этап Результат
Аналитика Определение эндпоинтов, типов данных, методов аутентификации
Проектирование Схема маршрутов, структура ответов, валидация параметров
Реализация Написание кода, регистрация роутов, обработчики, кеширование
Тестирование Модульные тесты (PHPUnit), ручное тестирование через curl
Деплой Развёртывание на боевом сервере, настройка мониторинга
Документация OpenAPI-схема или инструкция для разработчиков

Мы гарантируем соблюдение сроков и предоставляем пост-релизную поддержку в течение 30 дней. Свяжитесь с нами для оценки вашего проекта — мы проконсультируем по архитектуре и объёму работ. Закажите разработку кастомных эндпоинтов и сократите время интеграции в 2 раза.

Порядок разработки кастомного REST API

  1. Аудит — определяем список эндпоинтов, методов (GET/POST/PUT/DELETE) и структуры ответов.
  2. Проектирование схемы маршрутов — версионирование (/my-plugin/v1/), аргументы, валидация параметров.
  3. Реализация обработчиков — написание callback-функций, форматирование данных, обработка ошибок.
  4. Настройка аутентификации — Cookie (для админки), Application Passwords или JWT (для SPA/мобильных).
  5. Кеширование — Transients API или Redis, инвалидация при изменении данных.
  6. Тестирование через curl и PHPUnit, документация в OpenAPI-формате.

Стоимость разработки 2–3 кастомных эндпоинтов составляет от 15 000 рублей. Полноценный API с аутентификацией JWT и кешированием — от 40 000 рублей. Это лучше, чем прямые SQL-запросы с N+1 проблемами и уязвимостями к SQL-инъекциям.

Как отладить кастомный REST API WordPress?

Используйте curl -X GET https://site.com/wp-json/my-plugin/v1/projects -v для базовой проверки. Включите WP_DEBUG и WP_DEBUG_LOG в wp-config.php — ошибки PHP попадут в debug.log. Плагин Query Monitor покажет все SQL-запросы, выполненные во время вызова эндпоинта, и поможет выявить N+1 проблемы. Проверьте заголовки ответа: X-WP-Total должен содержать число записей, Content-Type: application/json. При ошибке 401 убедитесь, что permission_callback возвращает true или корректно проверяет права пользователя.

Почему кастомные эндпоинты лучше прямых SQL-запросов?

Кастомный REST API эндпоинт обеспечивает безопасность (фильтрация через WP API), кеширование (Transients/Redis) и версионирование. По нашим данным, переход на кастомные эндпоинты сокращает время на интеграцию в 2 раза и снижает количество ошибок на 60%. Примеры кастомных эндпоинтов: get_projects, create_order и др. Более 5 лет мы разрабатываем WordPress-решения, запущено 30+ проектов с кастомными REST API. Получите консультацию — оценим ваш проект и предложим оптимальное решение.