WP REST API(кастомное) — взаимодействие с WP сайтом.

В прошлой статье мы обсудили стандартное WP REST API, принцип чтения о нем информации и использования. В этой части рассмотрим создание и расширение существующего программного интерфейса.

Содержание

Вступление. WP REST API к кастомному типу записи

Предположим, есть задача создать тип записи. Рассмотрим код выполнения этой задачи, приведенный в официальной документации

<?php add_action( 'init', 'codex_book_init' ); /** * Register a book post type. * * @link http://codex.wordpress.org/Function_Reference/register_post_type */ function codex_book_init() { $labels = array( 'name' => _x( 'Books', 'post type general name', 'your-plugin-textdomain' ), 'singular_name' => _x( 'Book', 'post type singular name', 'your-plugin-textdomain' ), 'menu_name' => _x( 'Books', 'admin menu', 'your-plugin-textdomain' ), 'name_admin_bar' => _x( 'Book', 'add new on admin bar', 'your-plugin-textdomain' ), 'add_new' => _x( 'Add New', 'book', 'your-plugin-textdomain' ), 'add_new_item' => __( 'Add New Book', 'your-plugin-textdomain' ), 'new_item' => __( 'New Book', 'your-plugin-textdomain' ), 'edit_item' => __( 'Edit Book', 'your-plugin-textdomain' ), 'view_item' => __( 'View Book', 'your-plugin-textdomain' ), 'all_items' => __( 'All Books', 'your-plugin-textdomain' ), 'search_items' => __( 'Search Books', 'your-plugin-textdomain' ), 'parent_item_colon' => __( 'Parent Books:', 'your-plugin-textdomain' ), 'not_found' => __( 'No books found.', 'your-plugin-textdomain' ), 'not_found_in_trash' => __( 'No books found in Trash.', 'your-plugin-textdomain' ) ); $args = array( 'labels' => $labels, 'description' => __( 'Description.', 'your-plugin-textdomain' ), 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'show_in_menu' => true, 'query_var' => true, 'rewrite' => array( 'slug' => 'book' ), 'capability_type' => 'post', 'has_archive' => true, 'hierarchical' => false, 'menu_position' => null, 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ) ); register_post_type( 'book', $args ); }
Code language: HTML, XML (xml)

Результатом выполнения этого кода будет пункт «Books» и новый тип записи «book» на сайте. Но данные о записях данного типа будут не доступные по АПИ, для этого нужно изменить массив аргументов

<?php $args = array( 'labels' => $labels, 'description' => __( 'Description.', 'your-plugin-textdomain' ), 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'show_in_menu' => true, 'query_var' => true, 'rewrite' => array( 'slug' => 'book' ), 'capability_type' => 'post', 'has_archive' => true, 'hierarchical' => false, 'menu_position' => null, 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ), 'show_in_rest' => true,// включает отображение апи 'rest_base' => 'book',// путь для апи, по-умолчанию, равно типу записи 'rest_controller_class' => 'WP_REST_Posts_Controller'// класс, строящий апи, по-умолчанию "WP_REST_Posts_Controller" );
Code language: HTML, XML (xml)

Данный код создаст стандартный «вордпрессовский » API. Кстати, плюсом к включению АПИ в типе поста будет также включатся редактор Guttenberg в админке.

При этом автоматически будет сгенерированная схема.

Создадим WP REST API к какому-нибудь контенту

На самом деле, этот путь можно использовать и для АПИ типов постов, но зачем?.. ведь разработчики предусмотрели эту возможность, и я за то, чтоб максимально использовать все, что усмотрено разрабами.

Но тем не менее, рассмотрим этот способ. Создадим эндпоинт-функцию и прикрепим к ней маршрут

<?php function custom_rest_route( $get ) { return $get['message']; } function rest_callback() { register_rest_route( 'custom/v1', '/custom/(?P<message>\w+)', array( 'methods' => 'GET', 'callback' => 'custom_rest_route' )); } add_action( 'rest_api_init', 'rest_callback');
Code language: HTML, XML (xml)

Здесь «(?P\w+)» — обычное регулярное выражение. В данном случаи, перейдя по пути http://example.com/wp-json/custom/v1/custom/hello увидим hello на экране. Этот маршрут, также, появиться в схеме.

Этот способ можно использовать для API любой сложности, однако, согласно рекомендациям разработчиков — это способ для простейших случаев. Для более сложных случаев будет правильнее создавать класс, расширяющий WP_REST_Controller.

Расширяем WP_REST_Controller

Прежде, чем расширять класс, нужно знать его методы(это касается любого расширяемого класса). Класс WP_REST_Controller имеет более 25 методов, однако, для создания на его базе своего интерфейса достаточно знать 5:

  • register_routes — регистрация маршрутов(их может быть много);
  • get_items, get_item, create_item, update_item, delete_item — методы, отвечающие на запросы.

Я не буду ничего усложнять и просто перепишу созданное ранее в виде класса

<?php function rest_callback() { $route = new Custom_REST_Controller(); return $route->register_routes(); } add_action( 'rest_api_init', 'rest_callback'); class Custom_REST_Controller extends WP_REST_Controller { function register_routes() { register_rest_route( 'custom/v1', '/custom/(?P<message>\d+)', array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_item' ) )); } function get_item( $request ) { return new WP_REST_Response( $get['message'], 200 ); } }
Code language: HTML, XML (xml)

Поскольку мой пример только выводит надпись — я использую только get_item(). Вообще, это минимальный минимум для создания маршрута и эндпоинта.

Редактирование эндпоинтов и схемы. Фильтры

Редактирование результатов работы функции, согласно философии wordpress, происходит по средству фильтров. Данное утверждение касается абсолютно всех функций этого движка.

Работают фильтры так: есть функция

<?php function some_func( $args ) { // do something $args = apply_filters( 'slug', $args );// filter install // do something }
Code language: HTML, XML (xml)

Если в функции установлен фильтр, то передаваемые аргументы в этом фильтре можно изменить

<?php function filter_func( $args ) { // do something with args return $args; } add_filter( 'slug', 'filter_func', 10, 1 );
Code language: HTML, XML (xml)

Здесь 10 — приоритет выполнения функции фильтра, 1 — количество принимаемых аргументов. Приоритет может изменятся если функций-фильтров несколько, чем больше это число — тем позже будет срабатывать фильтр. И еще, регистрация фильтра(add_filter) должна происходить раньше, чем вызов функции, которую нужно отфильтровать.

Но хватит теории, изменим программный интерфейс. Для начала, нужно знать слаг фильтра, его можно найти в документации вордпресс.

Возьмем, для примера, функцию-эндпоинт, которая подготавливает присланный запрос к созданию нового пользователя. В ней есть следующий крючок для фильтра

<?php return apply_filters( 'rest_pre_insert_user', $prepared_user, $request );
Code language: HTML, XML (xml)

значит, чтоб вызвать фильтр к этой функции нужно написать

<?php add_filter( 'rest_pre_insert_user', 'rest_pre_insert_user_filter', 10, 2 );
Code language: HTML, XML (xml)

В этом случаи функция rest_pre_insert_user_filter() будет принимать 2 аргумента и, после фильтрации, всегда возвращать первый из них.

Для редактирования схемы ответа, аналогично, нужно знать слаг фильтра.

Добавление полей. Экшены

Чисто технически, экшены и фильтры — одно и тоже, но логически разное. Экшен вместо того чтоб изменять данные, дополняет. Допустим, есть функция

<?php function some_func( $args ) { // do something do_action( 'slug', $args );//вызов экшена // do something }
Code language: HTML, XML (xml)

аналогично фильтру, нужна экшн-функция и ее привязка именно на этот экшен

<?php function action_func( $args ) { // do something with args } add_action( 'slug', 'action_func', 10, 1 );
Code language: HTML, XML (xml)

Экшн-функция ничего не возвращает, в отличии от фильтра. Циферки при add_action имеют такой же смысл как и в add_filter.

Пример добавления дополнительного поля в запросе и схеме АПИ комментариев(взято в документации)

<?php add_action( 'rest_api_init', function () { register_rest_field( 'comment', 'karma', array( 'get_callback' => function( $comment_arr ) { $comment_obj = get_comment( $comment_arr['id'] ); return (int) $comment_obj->comment_karma; }, 'update_callback' => function( $karma, $comment_obj ) { $ret = wp_update_comment( array( 'comment_ID' => $comment_obj->comment_ID, 'comment_karma' => $karma ) ); if ( false === $ret ) { return new WP_Error( 'rest_comment_karma_failed', __( 'Failed to update comment karma.' ), array( 'status' => 500 ) ); } return true; }, 'schema' => array( 'description' => __( 'Comment karma.' ), 'type' => 'integer' ), ) ); } );
Code language: HTML, XML (xml)

По-умолчанию,цифры равны 10 и 1.

Заключение

В этой статье проведено ознакомление с принципами изменения и дополнения WP REST API. Если нужно только работать с дефолтным АПИ — читайте. Для получения более подробной информации рекомендую прочесть REST API Handbook. Это, так сказать, информация из первых рук, т.е. разработчиков ВП АПИ.

Источники

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

*

code