Эта задача крайне редкая для сайтов на вордпресс. Скажу прямо — в моей практика не было задач(возможно, я нуб или это потому, что апи делают серьезным проектам, а на вордпресс, зачастую, клепают более простые). В любом случаи, я считаю это нужно знать. Ведь это дает возможность, допустим, создать приложение по управлению блогом, не входя в блог(сайт) или тему на ReactJS. В этой статье я расскажу о WP API, которое получается при установке свежего вордпресс версии 5.2.4.
Содержание
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.
Источники