Эта задача крайне редкая для сайтов на вордпресс. Скажу прямо — в моей практика не было задач(возможно, я нуб или это потому, что апи делают серьезным проектам, а на вордпресс, зачастую, клепают более простые). В любом случаи, я считаю это нужно знать. Ведь это дает возможность, допустим, создать приложение по управлению блогом, не входя в блог(сайт) или тему на ReactJS. В этой статье я расскажу о WP API, которое получается при установке свежего вордпресс версии 5.2.4.
Содержание
- API — что это?
- Используем WP REST API
- Маршруты и точки входа
- Схема ответа
- Запросы и ответы
- Заключение
- Источники
API — что это?
API (программный интерфейс приложения, интерфейс прикладного программирования) (англ. application programming interface) — описание способов (набор классов, процедур, функций, структур или констант), которыми одна компьютерная программа может взаимодействовать с другой программой.
В нашем случаи, это способ взаимодействия между сайтом на ВП и приложением. Как и везде(по крайней мере, других вариантов я не встечал), это(обмен информации) реализовано в JSON-формате.
Используем WP REST API
Для использования АПИ сайта нужно знать пути к точкам входа(Routes & Endpoints). Эту информацию мы можем получить следующим образом
<?php $url = 'http://example.com/wp-json/';//если ЧПУ ссылки // не включены замените 'wp-json' на 'rest_route=' // запрос в общем случаи $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $url ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); $result = curl_exec( $ch ); // в случаи, если вы делаете запрос с админки // или с одного ВП сайта в другой(есть доступ // к классу WP_REST_Request) $request = new WP_REST_Request( 'GET', $url ); $result = rest_do_request( $request );
В результате, мы получим JSON-строку, декодировав которую(json_decode) — объект, содержащий всю информацию об АПИ сайта. Конечно, можно и в REST API Handbook посмотреть(там указаны дефолтные пути), но их можно изменять — об этом потом.
Рассмотрим маршрут чтения создания и редактирования поста.
Маршруты и точки входа
Рассмотрим маршрут ‘/wp/v2/posts’. Чтоб получить информацию об этом объекте — перейдем по ключу routes->{‘/wp/v2/posts’}. Вот полный объект содержащийся по этой ссылке(версия вордпресс 5.2.3, плагины отсутствуют)
stdClass Object ( [namespace] => wp/v2 [methods] => Array ( [0] => GET [1] => POST ) [endpoints] => Array ( [0] => stdClass Object ( [methods] => Array ( [0] => GET ) [args] => stdClass Object ( [context] => stdClass Object ( [required] => [default] => view [enum] => Array ( [0] => view [1] => embed [2] => edit ) [description] => Рамки в которых сделан запрос, определяют поля в ответе. [type] => string ) [page] => stdClass Object ( [required] => [default] => 1 [description] => Текущая страница коллекции. [type] => integer ) [per_page] => stdClass Object ( [required] => [default] => 10 [description] => Максимальное число объектов возвращаемое в выборке. [type] => integer ) [search] => stdClass Object ( [required] => [description] => Ограничить результаты до совпадающих со строкой. [type] => string ) [after] => stdClass Object ( [required] => [description] => Ограничить ответ записями опубликованными после заданной ISO8601 совместимой даты. [type] => string ) [author] => stdClass Object ( [required] => [default] => Array ( ) [description] => Ограничить выборку записями определенных авторов. [type] => array [items] => stdClass Object ( [type] => integer ) ) [author_exclude] => stdClass Object ( [required] => [default] => Array ( ) [description] => Убедиться что выборка исключает записи назначенные определенным авторам. [type] => array [items] => stdClass Object ( [type] => integer ) ) [before] => stdClass Object ( [required] => [description] => Ограничить ответ записями опубликованными до заданной ISO8601 совместимой даты. [type] => string ) [exclude] => stdClass Object ( [required] => [default] => Array ( ) [description] => Убедиться что выборка исключает определенные ID. [type] => array [items] => stdClass Object ( [type] => integer ) ) [include] => stdClass Object ( [required] => [default] => Array ( ) [description] => Ограничить выборку до определенных ID. [type] => array [items] => stdClass Object ( [type] => integer ) ) [offset] => stdClass Object ( [required] => [description] => Сдвиг выборки на определенное число объектов. [type] => integer ) [order] => stdClass Object ( [required] => [default] => desc [enum] => Array ( [0] => asc [1] => desc ) [description] => Упорядочить сортировку атрибута по возрастанию или убыванию. [type] => string ) [orderby] => stdClass Object ( [required] => [default] => date [enum] => Array ( [0] => author [1] => date [2] => id [3] => include [4] => modified [5] => parent [6] => relevance [7] => slug [8] => include_slugs [9] => title ) [description] => Сортировать коллекцию по атрибуту объекта. [type] => string ) [slug] => stdClass Object ( [required] => [description] => Ограничить выборку до записей с одним или несколькими установленными конкретными ярлыками. [type] => array [items] => stdClass Object ( [type] => string ) ) [status] => stdClass Object ( [required] => [default] => publish [description] => Ограничить выборку до записей с одним или несколькими установленными статусами. [type] => array [items] => stdClass Object ( [enum] => Array ( [0] => publish [1] => future [2] => draft [3] => pending [4] => private [5] => trash [6] => auto-draft [7] => inherit [8] => request-pending [9] => request-confirmed [10] => request-failed [11] => request-completed [12] => any ) [type] => string ) ) [categories] => stdClass Object ( [required] => [default] => Array ( ) [description] => Ограничить выборку до объектов с установленным указанным элементом в таксономии categories. [type] => array [items] => stdClass Object ( [type] => integer ) ) [categories_exclude] => stdClass Object ( [required] => [default] => Array ( ) [description] => Ограничить выборку до всех объектов кроме тех, что имеют указанные элементы назначенные в таксономии categories. [type] => array [items] => stdClass Object ( [type] => integer ) ) [tags] => stdClass Object ( [required] => [default] => Array ( ) [description] => Ограничить выборку до объектов с установленным указанным элементом в таксономии tags. [type] => array [items] => stdClass Object ( [type] => integer ) ) [tags_exclude] => stdClass Object ( [required] => [default] => Array ( ) [description] => Ограничить выборку до всех объектов кроме тех, что имеют указанные элементы назначенные в таксономии tags. [type] => array [items] => stdClass Object ( [type] => integer ) ) [sticky] => stdClass Object ( [required] => [description] => Ограничить выборку прилепленными объектами. [type] => boolean ) ) ) [1] => stdClass Object ( [methods] => Array ( [0] => POST ) [args] => stdClass Object ( [date] => stdClass Object ( [required] => [description] => Дата публикации объекта, по временной зоне сайта. [type] => string ) [date_gmt] => stdClass Object ( [required] => [description] => Время публикации объекта, по GMT. [type] => string ) [slug] => stdClass Object ( [required] => [description] => Буквенно-цифровой идентификатор для объекта уникальный для его типа. [type] => string ) [status] => stdClass Object ( [required] => [enum] => Array ( [0] => publish [1] => future [2] => draft [3] => pending [4] => private ) [description] => Именованный статус для объекта. [type] => string ) [password] => stdClass Object ( [required] => [description] => Пароль для защиты содержания и отрывка. [type] => string ) [title] => stdClass Object ( [required] => [description] => Название для объекта. [type] => object ) [content] => stdClass Object ( [required] => [description] => Содержимое объекта. [type] => object ) [author] => stdClass Object ( [required] => [description] => ID автора объекта. [type] => integer ) [excerpt] => stdClass Object ( [required] => [description] => Отрывок объекта. [type] => object ) [featured_media] => stdClass Object ( [required] => [description] => ID избранного медиа для объекта. [type] => integer ) [comment_status] => stdClass Object ( [required] => [enum] => Array ( [0] => open [1] => closed ) [description] => Открыты ли комментарии для объекта. [type] => string ) [ping_status] => stdClass Object ( [required] => [enum] => Array ( [0] => open [1] => closed ) [description] => Принимает ли объект уведомления. [type] => string ) [format] => stdClass Object ( [required] => [enum] => Array ( [0] => standard [1] => aside [2] => chat [3] => gallery [4] => link [5] => image [6] => quote [7] => status [8] => video [9] => audio ) [description] => Формат для объекта. [type] => string ) [meta] => stdClass Object ( [required] => [description] => Мета поля. [type] => object ) [sticky] => stdClass Object ( [required] => [description] => Считать ли объект прилепленным или нет. [type] => boolean ) [template] => stdClass Object ( [required] => [description] => Файл темы используемый для показа объекта. [type] => string ) [categories] => stdClass Object ( [required] => [description] => Элементы назначенные объекту в таксономии category. [type] => array [items] => stdClass Object ( [type] => integer ) ) [tags] => stdClass Object ( [required] => [description] => Элементы назначенные объекту в таксономии post_tag. [type] => array [items] => stdClass Object ( [type] => integer ) ) ) ) ) [_links] => stdClass Object ( [self] => http://wordpress.loc/wp-json/wp/v2/posts ) )
Проанализирую данный объект, кстати, аналогично можно прочесть и прочие объекты WP REST API.
Под ключем _links->self содержится абсолютная ссылка для запросов к апи постов этого сайта. methods — массив методов, которыми можно отправить запрос, endpoints — массив, содержащий описание возможных аргументов и методов их отправки; анализ одного из возможных аргументов — например context: required — обязателен ли, default дефолтное значение, enum массив возможных значений, description описание аргумента, type тип переменной, содержащейся в аргументе.
Context — массив возможностей для этого маршрута. В данном маршруте можно просматривать(view), вставлять(embed) и обновлять(edit) пост. Но с обновлением поста не все так просто — в конец маршрута нужно дописать идентификатор поста — а это уже новый маршрут, по этому я не буду это действие рассмартивать.
Объект endpoints содержит два массива потому, что первый описывает запрос на извлечение данных, второй — добавление.
Схема ответа
Знать, как составить запрос и куда его отправлять — это, хоть и большая, но все же часть дела. Другая часть — это обработка ответа, для чего нужно знать его схему. Данный код получает эту схему
<?php $url = 'http://example.com/wp-json/wp/v2/posts'; // запрос в общем случаи $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $url ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'OPTIONS' ); $result = curl_exec( $ch ); // в случаи, если вы делаете запрос с админки // или с одного ВП сайта в другой(есть доступ // к классу WP_REST_Request) $request = new WP_REST_Request( 'OPTIONS', $url ); $result = rest_do_request( $request );
декодировав строку получим объект. В объекте по ключу schema получим схему; она представляет собой ключ в объекте и тип данных, которую принимает переменная.
Запросы и ответы
Получим список постов, в которых есть слово «привет» — произведем обычный поиск, а также добавим условие: чтоб автором постов был автор с id = 1
<?php $url = 'http://example.com/wp-json/wp/v2/posts'; $args = array( 'search' => 'привет', 'author' => array( 1 ) ); // запрос в общем случаи $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $url . '?' . http_build_query( $args ) ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); $result = curl_exec( $ch ); // в случаи, если вы делаете запрос с админки // или с одного ВП сайта в другой(есть доступ // к классу WP_REST_Request) $request = new WP_REST_Request( 'GET', $url ); $request->set_param( 'search', 'привет' ); $request->set_param( 'author', array( 1 ) ); $result = rest_do_request( $request );
Создадим пост с заголовком «АПИ». Для этого нужна аутентификация, которая на данную версию(5.2.3) в ядро ВП не включено. Чтобы создать эту возможность — установите плагин WordPress REST API Authentication(или ему подобные). В плагине(конкретно в этом) есть настройки; я выбрал Basic Auth и вариант Username : Password , по этому мои заголовки в коде такие
<?php $url = 'http://example.com/wp-json/wp/v2/posts'; $args = array( 'title' => 'АПИ', ); $headers = array( 'Authorization:Basic ' . base64_encode( 'Username : Password' ) ); // запрос в общем случаи $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $url ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt($ch, CURLOPT_POSTFIELDS, $args ); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers ); $result = curl_exec( $ch ); // в случаи, если вы делаете запрос с админки // или с одного ВП сайта в другой(есть доступ // к классу WP_REST_Request) $request = new WP_REST_Request( 'POST', $url ); $request->set_param( 'search', 'привет' ); $request->set_headers( $headers ); $result = rest_do_request( $request );
При успешном создании поста будет отдан объект данных о посте, зашифрованный в JSON-строку. Если же произошла ошибка при создании — вернет информацию об ошибке.
Заключение
Здесь было рассмотрено WordPress REST API «из коробки»(если не учитывать плагин аутентификации, который, я надеюсь, скоро включат в ядро) движка. В одной из следующих статей рассмотрим возможности кастомизации маршрутов, схем и точек входа — в общем — WP API.