Статьи

Создание пользовательских конечных точек для WordPress REST API

В этом руководстве по WordPress REST API рассказывается о создании настраиваемой конечной точки WP-API . Сначала мы создадим дочернюю тему по умолчанию «Twenty Seventeen» , которая позволит нам добавить функциональность в нашу тему, а затем перейдем к регистрации нашей пользовательской конечной точки API.

WordPress REST API предоставляет вам больше, чем просто набор встроенных маршрутов. Вы также можете создавать собственные маршруты и конечные точки, используя те же API, которые использовались для создания маршрутов по умолчанию (например, функция register_rest_route() и класс WP_Rest_Controller и т. Д.). С WP-API у вас будет возможность интегрировать WordPress с другими экосистемами, что делает WordPress мощной и современной платформой для разработки приложений.

Вы можете создавать или регистрировать пользовательские конечные точки либо в плагинах, либо в темах.

Создание детской темы

В папке установки WordPress создайте папку для своей дочерней темы. Давайте назовем это twentyseventeen-child :

 cd /var/www/html/wp-content/themes mkdir twentyseventeen-child 

Создание папки дочерней темы

Затем создайте файл style.css :

 touch style.css 

И добавьте следующую информацию заголовка:

  

Поле « Шаблон» относится к имени папки родительской темы.

Перейдите в Внешний вид -> Темы в админке WordPress и выберите свою дочернюю тему:

Выбор дочерней темы WordPress в разделе тем WordPress

Затем нажмите кнопку « Активировать» , чтобы активировать свою дочернюю тему:

Кнопка Активировать

В папке темы добавьте файл functions.php со следующим исходным кодом:

 <?php // Add code here. 

Создание пользовательской конечной точки WP-API

Мы хотим создать новый маршрут, который позволит нам получать последние последние сообщения по идентификатору категории в следующем формате:

 http://localhost/wp-json/mytwentyseventeentheme/v1/latest-posts/<CATEGORY_ID> 

На этом этапе, если мы перейдем по указанному выше URL-адресу в нашем браузере, мы получим ошибку 404 с сообщением «Не найден маршрут, соответствующий URL-адресу и методу запроса» :

404 сообщение об ошибке

Это потому, что у нас на самом деле нет этого маршрута. Давайте изменим это!

В файле functions.php вашей темы добавьте следующий код:

 add_action('rest_api_init', function () { register_rest_route( 'mytwentyseventeentheme/v1', 'latest-posts/(?P<category_id>\d+)',array( 'methods' => 'GET', 'callback' => 'get_latest_posts_by_category' )); }); 

Мы используем register_rest_route() со следующими параметрами:

  • пространство имен, mytwentyseventeentheme/v1
  • путь к ресурсу с регулярным выражением для определения идентификатора категории, latest-posts/(?P<category_id>\d+)
  • массив опций, где мы определяем метод GET и get_latest_posts_by_category() обратного вызова get_latest_posts_by_category() которая обрабатывает запрос.

Пространство имен позволяет двум плагинам или темам использовать одни и те же пути маршрутов без конфликтов, а клиенты могут определять поддержку вашего пользовательского API, просто используя API /wp-json/wp/v2 и проверяя поле пространств имен .

Настройка пространств имен

Как видно из скриншота, пространство имен mytwentyseventeentheme/v1 которое мы использовали для нашего пользовательского маршрута, добавляется в поле пространств имен (этот снимок экрана сделан после полной реализации нашей пользовательской конечной точки; пожалуйста, продолжайте ниже).

Обратите внимание на часть ?P<category_id>\d+ . Это позволит нам получить идентификатор категории из текущего запроса. Это просто регулярное выражение, поэтому вы можете использовать обычную логику регулярных выражений для создания любого шаблона.

Реализация функции обратного вызова

На этом этапе, если мы посетим наш предыдущий URL, WordPress распознает маршрут, так как мы его определили. Но мы все равно получаем ошибку 500 с сообщением «Обработчик маршрута недействителен» .

Неверная ошибка маршрута 500

После регистрации пользовательского маршрута и указания функции get_latest_posts_by_category() в качестве обратного вызова, который будет вызываться для обработки и обработки запроса GET, давайте на самом деле реализуем его:

 function get_latest_posts_by_category($request) { $args = array( 'category' => $request['category_id'] ); $posts = get_posts($args); if (empty($posts)) { return new WP_Error( 'empty_category', 'there is no post in this category', array('status' => 404) ); } $response = new WP_REST_Response($posts); $response->set_status(200); return $response; } 

Сначала мы получаем аргумент category_id из параметра $request посредством прямого доступа. Затем мы создаем массив $args с ключом category установленным в значение category_id которое будет извлечено из маршрута.

Затем мы вызываем метод get_posts() для запроса сообщений с указанным идентификатором категории. Если мы получим пустой массив posts, мы вернем сообщение об ошибке, состоящее из кода empy_category , a there is no post in this category сообщении there is no post in this category сообщения и кода состояния 404 - все они передаются конструктору класса WP_Error .

Это скриншот, который мы получаем, если у нас есть пустая категория:

Результат из пустой категории

Наконец, мы создаем новый экземпляр класса WP_REST_Response ; мы передаем массив $posts ; мы устанавливаем 200 кодов состояния; и мы возвращаем ответ REST. Мы также можем напрямую вернуть массив $posts и он будет автоматически преобразован в JSON.

WP_Error и WP_REST_Response используются, чтобы убедиться, что конечная точка возвращает правильный ответ JSON.

Теперь, если мы вернемся в наш браузер и зайдем, например, на этот URL:

 http://<YOUR_SITE_DOMAIN>/wp-json/mytwentyseventeentheme/v1/latest-posts/1 

… Мы либо получим пустой массив, либо сообщения, относящиеся к категории ID 1 .

Вы также можете предоставить обратные вызовы санации и проверки в дополнение к своему основному обратному вызову.

Вы можете определить аргументы для каждого маршрута в виде массива с параметром args как и с параметром callback . В массив вы можете добавить несколько аргументов. Ключ - это имя аргумента, а значение - массив параметров для этого аргумента, таких как sanitize_callback или validate_callback .

  • validate_callback - это функция обратного вызова для проверки аргумента. Он принимает функцию, которой будет передано значение аргумента, и он должен вернуть true, если значение допустимо, или false в противном случае.
  • sanitize_callback - это функция обратного вызова, используемая для очистки значения аргумента перед его передачей в основную callback . Значение передается в качестве параметра этой функции.

Санитарная обработка и проверка параметров конечной точки

Вы можете проверить параметры, передаваемые конечной точке - в нашем случае ID категории - используя функцию validate_callback() :

 'args' => [ 'category_id' => array( 'validate_callback' => function($value, $request, $param) { return $value >= 6; }) ] 

Параметр является первым аргументом, переданным обратному вызову. Мы используем выражение $value >= 6 чтобы проверить, больше или равен переданный идентификатор категории шесть. Если мы передадим значение меньше шести, будет выдан ошибочный параметр (ы): category_id .

Ошибка неверного параметра

Санитарная обработка позволяет очистить параметры. Для очистки данных необходимо использовать функцию sanitize_callback() следующим образом:

 'args' => [ 'category_id' => array( 'sanitize_callback' => function($value, $request, $param) { if($value < 6){ return 6; }; }) ], 

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

Обратный вызов проверки будет иметь приоритет над обратным вызовом очистки. В нашем примере, если вы используете оба обратных вызова и отправляете недопустимое значение ( <6 ) для идентификатора категории, вы получите Invalid parameter (s): category_id error, который не даст sanitize_callback() шанс быть уволенным и дезинфицировать данные.

Обратите внимание, что вам может не потребоваться добавлять какие-либо проверки или дезинфекции, потому что может быть достаточно шаблона регулярных выражений, который вы используете в маршруте. Например, в нашем случае ?P<category_id>\d+ определяет URL, который принимает только положительные числа. Любой другой ввод выдаст ошибку «Обработчик маршрута недействителен» .

Неверный обработчик маршрута

Ограничение доступа к конечным точкам

Вы можете ограничить доступ к конечным точкам, используя функцию permission_callback() , которая проверяет, есть ли у пользователя необходимые разрешения на выполнение действия до вызова обратного вызова основного обработчика. Это позволяет вам сообщить клиенту, какие действия он может выполнить с определенным URL-адресом, не пытаясь сначала выполнить запрос.

Функция permission_callback() должна возвращать значение true или false или экземпляр класса WP_Error .

Вам просто нужно передать permission_callback в функцию register_rest_route() , которая позволяет вам добавлять разрешения, управляющие доступом к конечной точке. Например:

 add_action('rest_api_init', function () { register_rest_route( 'mytwentyseventeentheme/v1', 'latest-posts/(?P<category_id>\d+)',array( 'methods' => 'GET', 'callback' => 'get_latest_posts_by_category', 'permission_callback' => function() { return current_user_can('edit_posts'); } )); }); 

Обратный вызов current_user_can() вызывает функцию current_user_can() чтобы проверить, аутентифицирован ли пользователь и обладает ли он необходимой возможностью ( edit_posts ) для выполнения действия. Так что, если клиент не аутентифицирован , будет сгенерирована ошибка.

Если у вас нет прав, вы получите ошибку rest_forbidden :

Ошибка rest_forbidden

Мы также можем просто вернуть true из permission_callback чтобы разрешить доступ всем без какой-либо аутентификации.

Использование шаблона контроллера

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

Шаблон контроллера просто включает расширение встроенного класса WP_REST_Controller , который реализует базовую функциональность, необходимую для обработки HTTP-запросов, и позволяет вам воспользоваться надежным кодом с лучшими практиками, используемыми встроенными конечными точками WP-API.

Используя шаблон контроллера, вам нужно использовать метод register_routes() для регистрации ваших пользовательских маршрутов и get_items() , get_item() , create_item() , update_item() и delete_item() для реализации GET, POST, PUT и УДАЛИТЬ запросы.

Давайте теперь посмотрим на простой пример, преобразовав наш предыдущий пример в использование шаблона контроллера. В файле functions.php добавьте:

 class Latest_Posts_Controller extends WP_REST_Controller {} 

Далее вам нужно реализовать метод register_routes() где вы будете регистрировать свои маршруты:

 class Latest_Posts_Controller extends WP_REST_Controller { public function register_routes() { $namespace = 'mytwentyseventeentheme/v1'; $path = 'latest-posts/(?P<category_id>\d+)'; register_rest_route( $namespace, '/' . $path, [ array( 'methods' => 'GET', 'callback' => array( $this, 'get_items' ), 'permission_callback' => array( $this, 'get_items_permissions_check' ) ), ]); } } 

Мы просто вызываем встроенный метод register_rest_route() чтобы зарегистрировать маршрут для запроса GET.

Вам необходимо переопределить get_items_permissions_check() и get_items() в вашем контроллере:

  public function get_items_permissions_check($request) { return true; } 

Этот метод проверяет наличие необходимых разрешений для маршрута. Мы просто возвращаем true, чтобы каждый мог получить доступ к маршруту.

Далее мы переопределяем метод get_items() :

  public function get_items($request) { $args = array( 'category' => $request['category_id'] ); $posts = get_posts($args); if (empty($posts)) { return new WP_Error( 'empty_category', 'there is no post in this category', array( 'status' => 404 ) ); } return new WP_REST_Response($posts, 200); } 

Этот метод почти такой же, как наша предыдущая get_latest_posts_by_category() .

Это оно! Это два метода, которые мы должны переопределить в нашем примере. В более сложных сценариях вам необходимо переопределить другие методы для создания полностью работающей системы CRUD - то есть create_item() , update_item() , delete_item() и get_item() .

Наконец, нам нужно создать экземпляр нашего класса Latest_Posts_Controller и вызвать его метод register_routes() в rest_api_init action rest_api_init :

 add_action('rest_api_init', function () { $latest_posts_controller = new Latest_Posts_Controller(); $latest_posts_controller->register_routes(); } 

В этом простом примере шаблон контроллера может показаться не очень полезным, но для более сложных сценариев - например, когда у вас есть пользовательский тип записи и вам нужно предоставить пользовательский RESTful API для чтения, создания, обновления и удаления элементов с несколькими маршруты и конечные точки - вы могли бы воспользоваться концепциями ООП и шаблоном контроллера, чтобы лучше организовать свой код и использовать существующие классы.

Вывод

В этом руководстве мы увидели, как создать свой собственный маршрут (ы) для WP-API. Это позволит вам создавать мобильные и веб-клиенты для вашего веб-сайта WordPress, которые также могут взаимодействовать с вашими пользовательскими типами сообщений , а не только со встроенными типами WordPress (такими как сообщения и категории и т. Д.).