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

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

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

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

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

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

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

Этапы разработки

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

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

Разработка кастомных 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. Получите консультацию — оценим ваш проект и предложим оптимальное решение.

WordPress разработка: кастомные темы, плагины и WooCommerce

Клиент приходит с готовым сайтом на WordPress — и первое, что я вижу в DevTools: 47 активных плагинов, страница весит 6.8 MB, TTFB 2.4 с, в консоли пять конфликтующих версий jQuery. Это не редкость, а стандарт «доделанного» сайта, выросшего из шаблона в нечто живое, но неуправляемое. Мы решаем такие задачи под ключ — от аудита до деплоя. Оценим ваш проект за один рабочий день, свяжитесь.

WordPress занимает 43% рынка CMS (данные Wikipedia) — не потому что идеален, а потому что предсказуем, обширно задокументирован и имеет экосистему под любую задачу. Задача инженера — использовать эту экосистему аккуратно, не превращая сайт в помойку зависимостей. Мы помогаем найти баланс между функциональностью и производительностью, опираясь на 10-летний опыт и 80+ выполненных проектов.

Архитектурные решения и частые проблемы

Блокировка рендеринга из-за плагинов

Plugin A загружает jQuery 3.6, Plugin B — jQuery 1.12, тема — свой jQuery Migrate. В итоге wp_enqueue_scripts отдаёт три разных версии библиотеки, рендеринг страницы блокируется на 800 мс ещё до начала парсинга основного контента. Решается через wp_dequeue_script, централизованный контроль зависимостей и перевод некритичных скриптов в defer/async.

N+1 запросы и их решение

Разработчик написал WP_Query в цикле — каждый пост генерирует отдельный SQL-запрос. На странице с 20 постами это 21+ запрос к базе. MySQL начинает тупить, сервер греется. Фиксируется через post__in с prefetch или через переход на wpdb->get_results() с JOIN. Query Monitor — первый инструмент для диагностики.

WooCommerce под нагрузкой

Магазин с 15 000 SKU, без object caching, без Redis — при 200 одновременных пользователях wc_get_product() убивает базу. Транзиент-кэш WordPress не спасает: он пишет в базу, увеличивая нагрузку. Реальное решение — Redis через wp-redis или Memcached, плюс wp_cache_set()/wp_cache_get() в кастомном коде.

Как выбрать архитектуру: headless или монолит?

Выбор зависит от требований к производительности и сложности интерфейсов. Headless (REST API / WPGraphQL + Next.js) даёт прирост TTFB до 50% и изоляцию фронтенда, но требует более сложной инфраструктуры. Монолитная тема проще в поддержке для контентных проектов, где SEO критично и нужен прямой доступ к WP Rewrite. Мы помогаем определить оптимальный вариант на этапе аудита. Переход на headless улучшает LCP в 2.5 раза по сравнению с монолитом при правильной настройке кэширования — это подтверждено на 30+ проектах.

Стек и подходы в WordPress разработке

Разработка тем. Не используем page builders типа Elementor для продуктовых сайтов — они генерируют раздутый HTML и привязывают клиента к визуальному редактору навсегда. Кастомная тема на базе _s (underscores) загружается в 4 раза быстрее, чем тема на Elementor. Вместо этого: кастомная тема или блочная тема для Full Site Editing, Tailwind CSS через Vite, TypeScript для сложного JS.

Gutenberg и блочная разработка. Начиная с WordPress 5.0, Gutenberg — это не редактор, а платформа. Разрабатываем кастомные блоки через @wordpress/scripts, регистрируем через register_block_type() с block.json. Серверный рендеринг через PHP для SEO-критичных блоков, клиентский — для интерактивных. Inner Blocks для составных компонентов.

REST API и headless. WordPres как headless CMS через WP REST API v2 или WPGraphQL. Типичная схема: WordPress на поддомене cms.example.com, Next.js фронтенд на основном домене. ISR (Incremental Static Regeneration) для страниц блога — страница регенерируется в фоне при обращении после истечения revalidate, не блокируя пользователя. Для аутентифицированных запросов — JWT через jwt-authentication-for-wp-rest-api или Application Passwords (встроено с WP 5.6). Подробнее о REST API — Wikipedia.

WooCommerce. Расширяем через хуки и фильтры — никогда не правим core-файлы. Кастомные типы продуктов через WC_Product extension. Для сложной логики цен — woocommerce_get_price_html и woocommerce_product_get_price. Payment gateways пишем с нуля, наследуя от WC_Payment_Gateway. Интеграция с 1С — через CommerceML или кастомный REST endpoint.

Производительность. Обязательный стек: Redis Object Cache + Full Page Cache (LiteSpeed Cache или WP Rocket) + CDN для статики + WebP через add_image_size() с конвертацией. Lazy load нативный (loading="lazy") плюс кастомный для критичных изображений выше сгиба — preload через <link rel="preload">.

Подход Производительность Сложность разработки SEO Рекомендуется для
Монолитная тема Средняя Низкая Отличная Контентные сайты, блоги, лендинги
Headless (REST/GraphQL) Высокая Высокая Хорошая (с SSR) Веб-приложения, SPA, мультидомены
Headless + Next.js (ISR) Очень высокая Средняя Отличная Каталоги, новостные порталы

Кейс из нашей практики: WooCommerce‑магазин, LCP 9:00 с → 1.8 с

Магазин электроники, 40 000 SKU, WooCommerce + кастомная тема. PageSpeed Insights: LCP 9.2 с, CLS 0.41, INP 680 мс.

Диагноз:

  • Hero-изображение 3.8 MB JPEG, не оптимизированное, без srcset
  • 23 плагина загружали JS/CSS на каждой странице, включая страницы продуктов
  • wc_get_product() вызывался 60 раз на странице категории без кэширования
  • Шрифты загружались через Google Fonts (дополнительный DNS lookup)

Что сделали:

  • Hero — WebP 180 KB, <img fetchpriority="high" decoding="async">, srcset для 3 breakpoints
  • Условная загрузка плагинов через is_product(), is_cart(), is_checkout() — убрали 80% лишнего JS
  • Redis Object Cache, WC_Product prefetch через wc_get_products() с include
  • Шрифты — self-hosted через @font-face, font-display: swap
  • CLS победили через aspect-ratio на всех product card images

Результат: LCP 1.8 с, CLS 0.04, INP 140 мс. Core Web Vitals — зелёные. Клиент сократил расходы на хостинг на 240 000 руб в год после перехода на более дешёвый тариф, ставший возможным благодаря снижению нагрузки. Дополнительно замена 10 плагинов на один кастомный сэкономила ещё 80 000 руб в год на лицензиях.

Подробнее о методах диагностики Для аудита использовали Lighthouse CI, WebPageTest с эмуляцией мобильных сетей, а также кастомный плагин, логирующий все WordPress запросы. Полный отчёт включает рекомендации по каждому компоненту.

Процесс работы

  1. Аудит и аналитика. Анализ существующей кодовой базы, конкурентов, технических требований. Для нового сайта — семантическое ядро, UX-прототипирование.
  2. Архитектура. Решаем: монолит или headless. Определяем Custom Post Types, Custom Fields (ACF или нативные register_meta()), таксономии.
  3. Разработка. Локальное окружение: Docker (nginx + php-fpm + MariaDB). Git с pre-commit хуками для PHP CS Fixer и ESLint. Деплой через WP-CLI + SSH или Buddy.works CI/CD.
  4. Тестирование. PHPUnit для кастомных плагинов. Playwright для E2E критичных сценариев (добавить в корзину → оформить заказ → подтверждение). Lighthouse CI в пайплайне — падаем, если Performance Score < 85.
  5. Деплой и поддержка. Staging через WP Stagecoach или ручной клон. Мониторинг — UptimeRobot + Sentry для PHP ошибок. Обновления плагинов — через WP-CLI в тестовой среде сначала.

Как провести аудит WordPress сайта за 5 шагов?

  1. Проверьте wp-config.php — включён ли WP_DEBUG и WP_DEBUG_LOG. В продакшене они должны быть выключены.
  2. Откройте Query Monitor (или аналоги) и посмотрите количество запросов на главной. Норма — менее 30.
  3. Запустите Lighthouse — обратите внимание на LCP, CLS, INP. Если LCP > 2.5 с, ищите блокирующие ресурсы.
  4. Проверьте плагины на дублирование функционала (например, два плагина кэширования).
  5. Сделайте нагрузочный тест с помощью Locust или k6 — 200 одновременных визитов не должны вызывать ошибки тайм-аута.

Что вы получите в результате

  • Полностью кастомную тему или доработку существующей
  • Настроенные объектное кэширование (Redis/Memcached) и Full Page Cache
  • Оптимизированные медиафайлы (WebP, srcset, lazy load)
  • Документацию по структуре кода и инструкции по обновлению
  • Обучение контент-менеджеров работе с блоками Gutenberg
  • Гарантию бесперебойной работы в течение 30 дней после деплоя
  • Доступ к репозиторию с полной историей изменений

Ориентиры по срокам

Тип проекта Срок
Лендинг на кастомной теме 2–3 недели
Корпоративный сайт (10–30 страниц) 4–8 недель
WooCommerce-магазин (базовый) 6–10 недель
WooCommerce + кастомная логика + интеграции 3–6 месяцев
Headless WordPress + Next.js 8–16 недель

Стоимость рассчитывается индивидуально после аудита требований. Получите консультацию для предварительной оценки.

Типичные ошибки при разработке на WordPress

  • Прямое редактирование файлов темы — при обновлении темы все изменения теряются. Всегда используйте дочернюю тему или полностью кастомную.
  • update_post_meta() в цикле — каждый вызов отдельный UPDATE. Для массовых операций применяйте $wpdb->update() или update_metadata_by_mid().
  • Отключённый WP_DEBUG в разработке — скрытые PHP Notice засоряют error log и часто указывают на реальные проблемы.
  • Хранение медиа в Git — wp-content/uploads в .gitignore, синхронизация через WP-CLI media import или rsync.
  • Нет лимита на WP_Queryposts_per_page => -1 на странице с тысячами записей гарантирует таймаут.

Почему стоит доверить WordPress разработку профессионалам?

Мы на рынке более 10 лет, выполнили 80+ проектов, имеем сертификаты Automattic и опыт работы с WooCommerce на высоконагруженных площадках. Наши решения учитывают все нюансы: от совместимости плагинов до требований Core Web Vitals (рекомендации Google). После завершения проекта вы получаете не просто сайт, а документированную, тестированную и готовую к масштабированию платформу.

Для консультации и оценки вашего проекта — пишите или звоните. Мы отвечаем в течение часа в рабочее время. Закажите аудит уже сегодня.