Использование XML-RPC API Wordpress
WordPress предоставляет XML-RPC API для взаимодействия с данными WordPress (постами, пользователями, категориями, тегами и прочими таксономиями). Однако, функционал API из коробки даже не позволяет получить список постов из определенной категории - фильтр по категории просто отсутствует. Я, признаться, ожидал найти некий метод, который обеспечит возможности фильтрации постов подобно WP_Query, но нет..
Предлагаю посмотреть краткий пример, который отражает суть использования API WordPress, а после этого посмотрим как расширять API дополнительными методами.
Внимание!
Для корректной работы XML-RPC API WordPress нужны PHP расширения php7.0-xml
и php7.0-xmlrpc
! При установке, соответственно, указывайте свою версию PHP.
Выполнение XML-RPC запроса
Для работы с WordPress API вы можете использовать curl, file_get_contents() + stream_context_create() или wordpress-xmlrpc-client. Я приведу примеры с использованием cURL и file_get_contents().
Все запросы к API нужно отправлять на URL:
http://your-wordpress.site/xmlrpc.php
Отправить запрос с помощью cURL
function do_api_request_via_curl($url, $xmlRequest)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: text/xml']);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest);
$error = curl_error($ch);$data = xmlrpc_decode($xmlResponse);
if ($error) {
die('Error: ' . $error);
}
$response = curl_exec($ch);
return $response;
}
Отправить запрос с помощью file_get_contents
function do_api_request_via_fgc($url, $xmlRequest)
{
$options = [
'http' => [
'method' => 'POST',
'header' => 'Content-Type: text/xml',
'content' => $xmlRequest
]
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return $result;
}
Пример получения постов
Для формирования XML-RPC запроса и декодирования ответа я использовал стандартную библиотеку php5-xmlrpc (или php7.0-xmlrpc для PHP7):
sudo apt-get install php5-xmlrpc
XMLReader
Чтобы не ставить дополнительный PHP модуль xmlrpc, можно обойтись классом XMLReader для декодирования ответа API.
Пример формирования данных запроса к WordPress API для получения списка постов:
$xmlRequest = xmlrpc_encode_request('wp.getPosts', [1, 'WP_USER', 'WP_USER_PASSWORD', [
'post_status' => 'publish',
'post_type' => 'post',
'number' => 2,
's' => urlencode("приложени")
], ['post_title']]);
Отправляем запрос:
$xmlResponse = do_api_request_via_curl('YOUR_WP_URL', $xmlRequest);
Роль пользователя
Через API пользователь будет получать только посты, на которые у него есть права редактирования. Поэтому для получения всех постов, используйте учетку пользователя с ролью "Редактор" или выше.
И декодируем ответ:
$data = xmlrpc_decode($xmlResponse);
Расширение WordPress API
Приведу пример расширения WordPress API методом my.wpQuery, который принимает параметры в стандартном формате WP_Query. Добавление нового метода API в лучших традициях WordPress происходит в 2 этапа:
- Регистрируем метод и его обработчик;
- Пишем сам обработчик запроса.
Регистрируем API метод
add_filter('xmlrpc_methods', function($methods) {
$methods['my.wpQuery'] = 'xmlrpc_method_my_wp_query';
return $methods;
});
Обработчик API метода
function xmlrpc_method_my_wp_query($args) {
/** @var wp_xmlrpc_server $wp_xmlrpc_server */
global $wp_xmlrpc_server;
$wp_xmlrpc_server->escape($args);
$data = xmlrpc_decode($xmlResponse);
if (count($args) < 3) {
$error = new IXR_Error(400, __('Insufficient arguments passed to this XML-RPC method.'));
return $error;
}
$args = array_pad($args, 5, []);
list($blog_id, $username, $password, $query_args, $fields) = $args;
if (!$user = $wp_xmlrpc_server->login($username, $password)) {
return $wp_xmlrpc_server->error;
}
do_action('xmlrpc_call', 'mm.wpQuery');
$posts = wp_get_recent_posts($query_args);
$result = [];
foreach ($posts as $post) {
if (!current_user_can('edit_post', $post['ID'])) {
continue;
}
$result[] = !empty($fields) ? array_intersect_key($post, array_flip($fields)) : $post;
}
return $result;
}
Пример выполнения запроса my.wpQuery:
$xmlRequest = xmlrpc_encode_request('my.wpQuery', [1, 'WP_USER', 'WP_USER_PASSWORD', [
'category_name' => 'reviews',
'numberposts' => 2
], ['ID', 'post_title']]);
$xmlResponse = do_api_request_via_fgc($wpUrl, $xmlRequest);
$data = xmlrpc_decode($xmlResponse);
Используем функцию wp_get_recent_posts(), поскольку она, в отличие, от get_posts() возвращает посты как ассоциативные массивы вместо объектов WP_Post. Это позволяет без лишних движений извлечь только нужные поля постов, ну и API должен вернуть посты как ассоциативные массивы.
$posts = wp_get_recent_posts($query_args);
Ф-цию array_intersect_key() используем для выбора только необходимых полей, поскольку метод $wp_xmlrpc_server->_prepare_post(), который извлекает указанные поля для API метода wp.getPosts, есть protected и мы не можем его использовать в нашем API (разве что расширить класс wp_xmlrpc_server).
Пример использования API метода: https://gist.github.com/Sorbing/266b41c8fab37d9d5fd67f8ebccbd0cb
#wordpress api, #wordpress xml-rpc api, #extend wordpress api