Загрузка данных
Интеграция с WordPress API
1. Введение
Современный WordPress – это не только классическая CMS, но и полноценный headless-бэкенд. Начиная с версии 4.7 ядро WordPress включает REST API, который позволяет внешним приложениям, мобильным клиентам, фронтенд-фреймворкам и другим сервисам взаимодействовать с данными сайта.
До появления REST API использовался XML-RPC – более старый и громоздкий протокол. Сегодня REST API является стандартом де-факто для интеграций.
Основные сценарии использования:
headless-архитектура: WordPress служит только CMS, а фронтенд построен на React, Vue, Next.js и т.п.;
мобильные приложения;
интеграция с CRM, ERP, email-маркетингом;
автоматизация публикаций из внешних систем;
синхронизация контента между сайтами.
2. Архитектура WordPress REST API
WordPress REST API построен на принципах REST:
ресурсы доступны по URL;
используются стандартные HTTP-методы: GET, POST, PUT, PATCH, DELETE;
ответы возвращаются в формате JSON;
навигация и фильтрация осуществляются через query-параметры.
Базовый URL
Все маршруты начинаются с:
https://example.com/wp-json/
Основные маршруты ядра находятся под пространством имён wp/v2:
https://example.com/wp-json/wp/v2/
Основные ресурсы ядра
Ресурс Эндпоинт
Записи /wp/v2/posts
Страницы /wp/v2/pages
Медиафайлы /wp/v2/media
Категории /wp/v2/categories
Метки /wp/v2/tags
Пользователи /wp/v2/users
Комментарии /wp/v2/comments
Поиск /wp/v2/search
Настройки /wp/v2/settings
Индекс всех маршрутов можно посмотреть по адресу:
https://example.com/wp-json/
HTTP-методы и операции
Метод Операция Пример
GET Чтение /wp/v2/posts
POST Создание /wp/v2/posts
PUT Полное обновление /wp/v2/posts/123
PATCH Частичное обновление /wp/v2/posts/123
DELETE Удаление /wp/v2/posts/123?force=true
Для публичных данных аутентификация не требуется. Для создания, обновления или удаления – необходимы права и аутентификация.
3. Работа с публичными данными
Простой GET-запрос
Получить последние опубликованные записи:
curl https://example.com/wp-json/wp/v2/posts
Ответ – массив объектов с полями: id, date, title, content, excerpt, link, author, categories, tags и другими.
Вложенные данные _embed
Чтобы сразу получить связанные ресурсы (автор, изображения, категории), используется параметр _embed:
/wp-json/wp/v2/posts?_embed
Теперь в объекте появятся _embedded.author, _embedded.wp:featuredmedia и т.д.
Пагинация
/wp-json/wp/v2/posts?per_page=10&page=2
Заголовки ответа содержат:
X-WP-Total – общее количество записей;
X-WP-TotalPages – количество страниц.
Фильтрация и поиск
/wp-json/wp/v2/posts?search=wordpress&categories=5&orderby=date&order=desc
Полезные параметры:
search – поиск по тексту;
categories, tags – фильтры по ID;
after, before – фильтры по дате;
slug – получение записи по ярлыку;
_fields – выбрать только нужные поля;
context – уровень детализации: view, edit, embed.
Пример с _fields:
/wp-json/wp/v2/posts?_fields=id,title,link
4. Аутентификация
Для операций записи и доступа к приватным данным нужна аутентификация.
4.1. Cookie-аутентификация (для frontend того же сайта)
Если JavaScript выполняется на том же сайте, где установлен WordPress, можно использовать cookie и nonce.
В PHP-шаблоне нужно передать nonce:
wp_localize_script('my-script', 'wpApiSettings', [
'root' => esc_url_raw(rest_url()),
'nonce' => wp_create_nonce('wp_rest'),
]);
В JavaScript:
fetch('/wp-json/wp/v2/posts', {
headers: {
'X-WP-Nonce': wpApiSettings.nonce
}
})
.then(res => res.json())
.then(posts => console.log(posts));
4.2. Application Passwords (WP 5.6+)
Самый простой способ для серверных интеграций и тестирования.
1. В админке перейдите: Пользователи → Профиль → Пароли приложений.
2. Создайте новый пароль приложения.
3. Используйте Basic Auth: логин – имя пользователя, пароль – сгенерированный пароль приложения.
Пример с curl:
curl -u "username:application_password" \
https://example.com/wp-json/wp/v2/posts
Пример на PHP:
$url = 'https://example.com/wp-json/wp/v2/posts';
$args = [
'headers' => [
'Authorization' => 'Basic ' . base64_encode('username:application_password')
]
];
$response = wp_remote_get($url, $args);
if (is_wp_error($response)) {
// обработка ошибки
}
$posts = json_decode(wp_remote_retrieve_body($response));
4.3. JWT-аутентификация
Для сторонних фронтенд-приложений часто используют плагин JWT Authentication for WP REST API.
Устанавливается плагин.
В wp-config.php добавляются секретные ключи.
Клиент отправляет POST /wp-json/jwt-auth/v1/token с логином и паролем.
Сервер возвращает токен.
Далее токен передаётся в заголовке Authorization: Bearer <token>.
JWT удобен для SPA-приложений и мобильных клиентов.
4.4. OAuth
Для публичных приложений, работающих с данными пользователей, рекомендуется OAuth 2.0 через плагины. Это более сложная схема, но она безопаснее для случаев, когда приложение действует от имени разных пользователей.
5. Создание контента через API
Создание записи
curl -X POST \
-u "username:application_password" \
-H "Content-Type: application/json" \
-d '{
"title": "Новая запись",
"content": "Текст записи",
"status": "draft",
"categories": [3],
"tags": [7]
}' \
https://example.com/wp-json/wp/v2/posts
Успешный ответ – объект созданной записи с id.
Обновление записи
curl -X PATCH \
-u "username:application_password" \
-H "Content-Type: application/json" \
-d '{"status": "publish"}' \
https://example.com/wp-json/wp/v2/posts/123
Загрузка медиафайла
Bash
curl -X POST \
-u "username:application_password" \
-F "file=@/path/to/image.jpg" \
-F "caption=Описание изображения" \
https://example.com/wp-json/wp/v2/media
Ответ содержит id, source_url, media_details и др.
6. Расширение REST API
6.1. Включение REST API для произвольных типов записей
При регистрации произвольного типа записи необходимо указать:
register_post_type('portfolio', [
'public' => true,
'show_in_rest' => true,
'rest_base' => 'portfolio', // URL: /wp-json/wp/v2/portfolio
'supports' => ['title', 'editor', 'thumbnail', 'excerpt'],
]);
6.2. Регистрация мета-полей
Чтобы кастомные поля были доступны через REST API:
register_post_meta('post', 'custom_field', [
'show_in_rest' => true,
'single' => true,
'type' => 'string',
]);
После этого поле появится в объекте записи и его можно будет обновлять через API.
6.3. Создание собственного маршрута
add_action('rest_api_init', function () {
register_rest_route('myapp/v1', '/latest-posts/', [
'methods' => 'GET',
'callback' => function ($request) {
$posts = get_posts([
'numberposts' => $request->get_param('per_page') ?: 5,
'post_status' => 'publish',
]);
$data = [];
foreach ($posts as $post) {
$data[] = [
'id' => $post->ID,
'title' => $post->post_title,
'link' => get_permalink($post->ID),
'thumbnail' => get_the_post_thumbnail_url($post->ID, 'medium'),
];
}
return $data;
},
'permission_callback' => '__return_true', // публичный маршрут
'args' => [
'per_page' => [
'validate_callback' => function ($param, $request, $key) {
return is_numeric($param) && $param > 0 && $param <= 20;
}
]
]
]);
});
Маршрут будет доступен по адресу:
https://example.com/wp-json/myapp/v1/latest-posts?per_page=5
6.4. Добавление вычисляемых полей
register_rest_field('post', 'reading_time', [
'get_callback' => function ($post) {
$content = get_post_field('post_content', $post['id']);
$words = str_word_count(strip_tags($content));
return ceil($words / 200); // минут чтения
},
'schema' => [
'description' => 'Время чтения в минутах',
'type' => 'integer',
],
]);
7. Пример интеграции с JavaScript-фронтендом
import { useEffect, useState } from 'react';
function LatestPosts() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('https://example.com/wp-json/wp/v2/posts?per_page=6&_embed')
.then(res => res.json())
.then(data => {
setPosts(data);
setLoading(false);
});
}, []);
if (loading) return <p>Загрузка...</p>;
return (
<ul>
{posts.map(post => (
<li key={post.id}>
<a href={post.link}>{post.title.rendered}</a>
</li>
))}
</ul>
);
}
Для production-интеграций рекомендуется:
кэшировать ответы;
использовать переменные окружения для URL API;
обрабатывать ошибки сети;
ограничивать количество запросов.
8. Безопасность и производительность
Безопасность
1. Всегда используйте HTTPS – иначе учётные данные и данные контента передаются в открытом виде.
2. Проверяйте права в собственных маршрутах через permission_callback.
3. Валидируйте и санируйте входные данные с помощью validate_callback и sanitize_callback.
4. Не выводите приватные данные через show_in_rest без необходимости.
5. Ограничивайте доступ к пользователям – эндпоинт /wp/v2/users может раскрывать email и имена.
6. Используйте application passwords вместо основного пароля для серверных интеграций.
7. Настройте CORS, если фронтенд живёт на другом домене:
add_filter('allowed_http_origins', function ($origins) {
$origins[] = 'https://app.example.com';
return $origins;
});
Производительность
Используйте параметр _fields, чтобы не получать лишние данные.
Включайте кэширование ответов на стороне клиента.
Для тяжёлых запросов рассмотрите транзиентное кэширование на стороне сервера.
При массовой загрузке медиафайлов используйте асинхронные очереди.
Если REST API отдаёт слишком много лишних данных, изучите плагин WPGraphQL как альтернативу.
9. Типичные проблемы и их решение
1. Ошибка 404 при обращении к /wp-json/
Решение: обновите постоянные ссылки:
Настройки → Постоянные ссылки → Нажать «Сохранить изменения».
Либо проверьте, что mod_rewrite включён на сервере.
2. CORS-ошибка в браузере
Решение: добавьте домен в разрешённые origin через фильтр allowed_http_origins или настройте прокси.
3. Mixed Content: HTTPS-сайт запрашивает HTTP-API
Решение: используйте только HTTPS-адрес API и проверьте настройки siteurl / home.
4. Не удаётся создать запись: 401 Unauthorized
Решение: проверьте заголовок Authorization, правильность application password и права пользователя (edit_posts).
5. Кастомное поле не отображается в API
Решение: убедитесь, что при регистрации мета-поля указан show_in_rest => true.
6. Произвольный тип записи не виден в API
Решение: при регистрации CPT добавьте show_in_rest => true и rest_base.
10. Практическое задание
Создайте простую интеграцию:
1. На тестовом сайте WordPress включите application password для пользователя-редактора.
2. Через REST API создайте черновик записи с заголовком и текстом.
3. Загрузите изображение через /wp/v2/media.
4. Обновите созданную запись, установив загруженное изображение как миниатюру.
5. Напишите собственный REST-маршрут /wp-json/custom/v1/recent-posts/, который возвращает последние 5 опубликованных записей с миниатюрами и ссылками.
6. Проверьте маршрут через браузер или Postman.