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 );
}

Результатом выполнения этого кода будет пункт «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"
	);

Данный код создаст стандартный «вордпрессовский » 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>\ц+)', array(
        'methods' => 'GET',
        'callback' => 'custom_rest_route'
    ));
}
add_action( 'rest_api_init', 'rest_callback');

Здесь «(?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 );
    }
}

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

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

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

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

<?php
function some_func( $args ) {
    // do something
    $args = apply_filters( 'slug', $args );// filter install
    // do something
}

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

<?php
function filter_func( $args ) {
    // do something with args
    return $args;
}
add_filter( 'slug', 'filter_func', 10, 1 );

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

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

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

<?php
return apply_filters( 'rest_pre_insert_user', $prepared_user, $request );

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

<?php
add_filter( 'rest_pre_insert_user', 'rest_pre_insert_user_filter', 10, 2 );

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

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

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

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

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

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

<?php
function action_func( $args ) {
    // do something with args
}
add_action( 'slug', 'action_func', 10, 1 );

Экшн-функция ничего не возвращает, в отличии от фильтра. Циферки при 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'
        ),
    ) );
} );

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

Заключение

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

Источники

«Локальное» SEO. HTML тег meta

HTML тег meta — тег, предназначенный поисковым роботам. Именно они(теги) являются основными источниками информации о содержимом страницы при индексации ботами. В множественном числе(о теге meta)потому, что их много видов и все они нужны. И кста, когда вы нажимание кнопку «Поделится» — внешний вид репоста формируется специальными метатегами. Нет, вроде как, могут и обычные использоваться, но мы о всех технических моментах ниже и поговорим.

Содержание

Синтаксис тега «meta»

HTML тег meta — одиночный тег который размещается исключительно блоке head. Имеет четыре атрибута: name, content, charset и http-equiv. Первые два — те, которые и образуют мета-данные страницы

<head>
    <title>...</title>
    <meta charset="utf-8"/>
    <meta name="title" content="..."/>
    ...
</head>

Приблизительно так выглядит html-разметка страницы. Кодировку(charset) достаточно указать единожды.

А теперь перейдем к рассмотрению значений атрибута name, ведь он, имхо, самый важный(на пару с content) парень. Он может иметь 7 значений:

  1. title — сео название документа, до 70 символов;
  2. application-name — в случаи, если это веб-приложение — то в content его название;
  3. author — автор данного документа:
  4. description — описание документа. до 160 символов;
  5. generator — если документ сгенерирован программой — название этой программы;
  6. keywords — ключевые слова, до 130 символов, до 10 фраз через кому;
  7. viewport — поиска и индексации страницы не касается, от него зависит отображение страницы при масштабировании. Крайне рекомендую ко всем страницам, в head добавить
<meta name="viewport" content="width=device-width, initial-scale=1.0">

Как пишет support google «каждый атрибут контента может содержать до 1024 символов. Пользовательский поиск может обрабатывать до 50 метатегов для каждой страницы…»

Протокол Open Graph

Протокол Open Graph позволяет любой веб-странице стать полноценным объектом в социальных сетях. Например, протокол используется на Facebook, чтобы разрешить любой веб-странице иметь такую же функциональность, как и любой другой объект на Facebook.

Иначе говоря — это метаданные, по которым современные социальные сети строят отображение репоста.

В этом протоколе есть свой атрибут, который полностью замещает name, — это property. У этого атрибута также есть свои значения:

Основные:

  • og:title — аналог title в name;
  • og:type — тип объекта от значения этого атрибута зависит наличие других свойств;
  • og:image — значение этого метатега должно содержать ссылку на изображение(репоста);
  • og:url — канонический урл, говоря простыми словами — постоянная ссылка на пост.

Дополнительные(необязательные, но рекомендуемые)

  • og:audio — ссылка на аудиофайл страницы, если есть;
  • og: description — аналог description в name;
  • og:determiner — слово, которое появляется перед названием этого объекта в предложении. Строковое значение, которое является членом перечисления(an, a, the…);
  • og:locale — тег физического местоположения в формате language_TERRITORY(en_US) ;
  • og:locale:alternate — альтернативные локали, каждая с которых записывается в свой тег;
  • og:site_name — если это страница сайта, то здесь — название сайта;
  • og:video — ссылка на видеофайл, если он есть.

Разметка Twitter Cards

Это отдельная разметка метатегов созданная Twitterом для построения твитов. Это те же мета-теги, что и в обычном HTML.

Начинается она с объявления ее поддержки

<meta name="twitter: card" content = "summary"> </ meta>

далее, должна идти одна из двоих строк, в зависимости от-того, у кого есть твит-аккаунт

<--! аккаунт есть у проекта -->
<meta name="twitter: site" content="@название аккаунта"/>

<--! аккаунт есть у автора страницы -->
<meta name="twitter: creator" content="@название аккаунта"/>

После этого, твиттер воспринимает нижеследующую обычную Open Graph разметку.

Заключение

Здесь рассмотрено техническое использование тега <meta>. Он который является основным, но не единственным(теги a, h%d, p…), для СЕО страницы. Однако же, если содержимого метатегов не будет в заголовках(h1, h2…) или параграфах(p) — поисковые роботы обидятся на сайт и в результатах поиска вы его не увидите. И, кстати, если вам нужно больше инфы по Open Graph — загляните сюда.

Источники