Меню ×
RESTful API в MODX Rrevolution

RESTful API в MODX Rrevolution

В MODX 2.3 был замечен удобный способ разработки API-интерфейсов RESTful поверх MODX. Это делается с поддержкой класса modRestService и производных modRestController. Он поддерживает большое количество интересных функций для взаимодействия с экземплярами xPDOObject. Цель этого документа - предоставить вам информацию, нужную для создания собственного API.

В кратце

  1. Создайте файл index.php, который обрабатывает загрузку MODX, настраивает службу REST с правильной конфигурацией и передает запрос контроллеру.
  2. Создайте файл .htaccess, который направляет все запросы (в поддиректории или в конкретном домене) в index.php
  3. Создайте контроллеры для каждой из ваших конечных точек

Создание обработчика загрузки MODX

Классы modRestService и modRestController значительно облегчат вашу работу, но вам нужно настроить некоторый базовый код для его подключения. Для этого документа мы предполагаем, что вы помещаете свой API в папку /rest/, при необходимости корректируйте пути.

Сначала создайте файл rest/index.php, который выглядит примерно так:

	
<?php
// Загрузить MODX
require_once dirname(dirname(__FILE__)) . '/config.core.php';
require_once MODX_CORE_PATH . 'model/modx/modx.class.php';
$modx = new modX();
$modx->initialize('web');
$modx->getService('error','error.modError', '', '');
// Загрузить любые классы или пакеты (модели), которые вам потребуются
$path = $modx->getOption('mypackage.core_path', null,
  $modx->getOption('core_path').'components/mypackage/') . 'model/mypackage/';
$modx->getService('mypackage', 'myPackage', $path);
// Загрузить класс modRestService и передать ему некоторую базовую конфигурацию
$rest = $modx->getService('rest', 'rest.modRestService', '', array(
   'basePath' => dirname(__FILE__) . '/Controllers/',
   'controllerClassSeparator' => '',
   'controllerClassPrefix' => 'MyController',
   'xmlRootNode' => 'response',
));
// Подготовить запрос
$rest->prepare();
// Удостовериться, что пользователю предоставлены необходимые права доступа; вернуть пользователю ошибку 401 в обратном случае
if (!$rest->checkPermissions()) {
   $rest->sendUnauthorized(true);
}
// Выполнить запрос
$rest->process();
?>
	

После этого вам необходимо убедиться, что все запросы к вашей папке /rest/ действительно обрабатываются сервером REST. Чтобы сделать это, добавьте следующее в ваш.htaccess (или эквивалент в nginx или других системах) в корне вашего сайта:

Настройка сервера на Apache

	
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(.*)$ rest/index.php?_rest=$1 [QSA,NC,L]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ rest/index.php [QSA,NC,L]
	

Настройка сервера на NGINX

	
location /rest/ {
   try_files $uri @modx_rest;
}

location @modx_rest {
   rewrite ^/rest/(.*)$ /rest/index.php?_rest=$1&$args last;
}
	

Ежели вы незамедлительно обнаружите /rest/foobar в вашем браузере, вы должны унаследовать ошибку, что показывает на то, что ваш API работает.

	
{
 success: false,
 message: "Method not allowed",
 object: [ ],
 code: 405
}
	

Теперь мы можем начать с фактической разработки API!

Точки доступа к API

Действительный API складывается изо много окончательных точек. Ежели вы желаете организовать безукоризненный RESTful API, всякая окончательная крапинка будет согласоваться «ресурсу» (не безоговорочно варианту изо левосторонного древа MODX! ), И различные HTTP-глаголы (GET, POST, PUT и DELETE) будут употребляться ради взаимодействия с определенными объектами. Допустим, вы создаете API ради управления перечнем дел, у вас могут являться «элементы» окончательной точки с последующими действиями:

  • GET /items: возвращает элементы в вашем списке дел
  • GET /items/15: возвращает элемент с первичным ключом 15
  • POST /items: создать новый элемент в списке дел
  • PUT /items/15: обновить одно или несколько значений в вашем списке дел с помощью первичного ключа 15
  • DELETE /items/15: удалить элемент с помощью первичного ключа 15

В глобальной сети интернет видимо-невидимо противоречат про то, как назвать ваши окончательные точки - в данном случае мы облюбовали многочисленные «пункты». Стоит заметить, что у нас нет окончательных точек, в том числе /items/create, - такое уже покрыто POST ради /items и представляется основным аспектом учения API RESTful.

Дабы организовать окончательную точку ингредиентов (items), вам необходимо организовать регулятор ингредиентов (items controller). Как следует из конфигурации, какую мы дали в modRestService ранее, и значений по умолчанию, всякий регулятор вынужден завязываться с MyController, укладываться в указатель /rest/Controllers/, а файл вынужден согласоваться имени окончательной точки с суффиксом .php. Оттого сотворите новоизобретенный документ /rest/Controllers/Items.php и скопируйте в него поступающий код:

	
class MyControllerItems extends modRestController {
   public $classKey = 'ToDoItem';
   public $defaultSortField = 'sortorder';
   public $defaultSortDirection = 'ASC';
}
	

Предполагая, что ToDoItem представляется именованием позволительного выводного xPDOObject, и вы навалили его где-то с поддержкой $modx-> addPackage() (например, в свой разряд Service, некоторый мы вытребовали в index. php), сейчас у вас есть абсолютно многофункциональный RESTful API для ваших предметов ToDoItem. Элементарно спросите /rest/items, и данный требование обязан отдавать ваши ToDoItems в привлекательном формате JSON.

Если у вас нет готового пакета, вы также можете установить для свойства classKey значение «modResource» и для defaultSortField значение «id», чтобы настроить API для всех ресурсов.

	
{
 results: [
   {
      id: 1,
      sortorder: 1,
      name: "Заканчиваем документировать RESTful API",
      added: "2020-05-14",
      target_completion_date: "2020-05-14",
      assigned_to: ""
   },
   // ...
 ],
 total: 1
}
	

Это как волшебство! Но вы знаете, что еще лучше? Это полноценный API сейчас... И если вы вернетесь к действиям, которые мы упоминали ранее, все они будут работать "из коробки". Например, /rest/items/1, вернет только элемент to do с идентификатором 1. Чтобы проверить POST, PUT и DELETE, вам, вероятно, потребуется использовать что-то вроде Postman или curl для отправки правильных запросов, но теперь они также должны быть функциональными.

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

Улучшаем работу с точками доступа к API

Большая часть следующей работы сводится к тому, чтобы сделать ваши конечные точки более умными и добавить их больше. Возможно, вы захотите изменить способ возврата ваших данных, отфильтровать ненужные данные и многое другое. У ModRestController есть все опции и хуки для вас, чтобы сделать это.

Каждый из запросов передается определенному методу в вашем контроллере. Это означает, что когда вы, например, запрашиваете GET /items, который возвращает список объектов, он обрабатывается методом modRestController.getList(). Вот как запросы направляются на контроллер:

  • GET /items: modRestController.get(), который вызывает modRestController.getList()
  • GET /items/5: modRestController.get(), который вызывает modRestController.read()
  • POST /items: modRestController.post()
  • PUT /items/5: modRestController.put()
  • DELETE /items/5: modRestController.delete()

Эти методы по умолчанию делают то, что вы ожидаете от них, с некоторой разумной обработкой ошибок и - по большей части - не нуждаются в настройке. Существуют также такие методы, как modRestController.beforePost(), modRestController.beforePut(), modRestController.beforeDelete(), которые позволяют предотвратить действие (создание, обновление или удаление объекта соответственно) путем возврата false. Обсуждаемый объект доступен через $this->object, так что вы можете убедиться, что у пользователя есть разрешение на выполнение действия или другую подготовку. Существует также modRestController.afterRead(), modRestController.afterPost(), modRestController.afterPut() и modRestController.afterDelete() для выполнения действий после завершения действия. Этим методам передается массив по ссылке, который содержит объект, который должен быть возвращен.

Похожие материалы

Revolution дорос уже до версии 2.3.2, но большинство разработчиков не спешит его использовать, так как документация еще не полная, да и статей на русском очень мало.

Сниппет предназначен для вывода списка ресурсов. Является продвинутой заменой для getResources: обладает всеми его возможностями, но лишен недостатков. Умеет правильно сортировать ТВ параметры, присоединять таблицы при выборке, включать и исключать категории из разных контекстов и еще много чего.

Для создания поиска по сайту необходимо установить пакет SimpleSearch. Затем в ресурсах создаем ресурс ПОИСК и вписываем туда По вашему запросу ничего не найдено. Попробуйте ввести похожие по смыслу слова, чтобы получить лучший результат.. Запоминаем id этого ресурса, это страница вывода результатов поиска. В шаблон где находится сама форма поиска вставляем следующий код:

наверх