MODX и REST

Раз уж зашла тема про REST хочу написать серию заметок о том, как обстоят дела с построением REST архитектуры в MODX или о том, как сделать API приложение на базе MODX.


Зачем это вообще может быть нужно

Приведу три простых примера
1. MODX работает как фреймворк с админкой. Фронт реализован через какой-нибудь ReactJS, а не классические шаблоны. Чтобы фронтэнд-фреймворк мог отобразить информацию, передавать запросы пользователя и тем более админа в MODX ему нужно обращаться к API MODX.

2. Мобильное приложение привязанное к проекту. Также нужна система обмена данными. Причем не просто обращение к общей базе данных, а полноценное срабатывание процессоров, событий и т.п.

3. Публичное API, когда один сайт предоставляет информацию (или принимает ее) другим сайтам/приложениям посредством API. Как мы обмениваемся информацией с различными CRM, справочниками, службами доставки и платежными системами.

Варианты реализации в MODX

1. Сделать приложение-компонент.

Можно слать все запросы на один коннектор (php файл, находящийся в каталоге assets/components/component_name/), который в зависимости от action будет разруливать эти запросы, отсылая их дальше в контроллеры или процессоры компонента и возвращать ответ. Цель скорее всего будет достигнута, приложение будет делать то, что от него требуется, но это не разу не REST.

REST отсылает каждый запрос на свой отдельный уникальный адрес
Несколько примеров
GET  /api//pages/   -  вывести  список страниц
GET  /api/pages/4/  - вывести страницу номер 4
PUT  /api/pages/4/   - а это уже изменить страницу 4
DELETE  /api/pages/4/  -   а здесь уже удалить страницу 4
POST /api/orders/   -  создать новый заказ
POST  /api/users/  - создать нового пользователя

Как можно заметить — один адрес может принимать разные методы запросов (GET, POST, PUT, DELETE) и в зависимости от метода выполнять разные действия. Но адрес для каждого объекта, каждой отдельной сущности должен быть уникальным.
Работаете со страницами — будьте добры обращаться к /pages/
Работаете с заказами — милости просим в /orders/

2. Другой вариант, который уже больше подходит для концепции REST — отсылаем все запросы как и договаривались на адрес по маске /api/**/*
MODX предсказуемо выдаст событие onPageNotFound — ну а дальше как завещал @Василий Наумкин выстраиваем плагин маршрутизации — и делаем что захотим.

Однако этот метод еще хуже первого.
  • Во первых решение само по себе костыль. Ну бред же — на основе события «Страница не найдена» делать маршрутизацию. Этот костыль хорошо подходит для разовых каких то страниц, вроде списка пользователей. Но не для построения CRUD API
  • Ну и такой плагин будет являть толстым контроллером. То есть весь массив запросов будет разруливать в одно лицо. Тогда как для каждой сущности должен быть свой отдельный контроллер.
3. Не последний, но основной для статьи вариант — встроенный в MODX еще со времен MODX 2.3, модуль modRestController, позволяющий не без бубна реализовать более менее рабочее RESTFul API.

На этом варианте и остановлюсь для начала.
В сообществе уже публиковался кое какой материал по modRestController. Однако ничего более менее полноценного не было. Вообще русскоязычного материала в этом направлении мало.
Кроме того мы договорились с @Иван Бочкарев о том, что я сделаю перевод документации для русскоязычного раздела MODX.

Чтобы не разворачивать простыню текста разобью материал на несколько публикаций.
План примерно такой:
1. Вводная часть. Мы здесь.
2. Перевод документации
3. Внедрение modRestController на практике. Примеры, Пошаговая реализация.
4. Поговорим о плюсах и минусах, обсудим сторонние альтернативные варианты, не из ядра MODX.
5. Возможно реализуем практику на альтернативных решениях.

До скорого.
Николай Савин
19 сентября 2019, 07:45
modx.pro
3
628
+19
Поблагодарить автора Отправить деньги

Комментарии: 4

Василий Наумкин
19 сентября 2019, 08:10
3
+4
Другой вариант, который уже больше подходит для концепции REST — отсылаем все запросы как и договаривались на адрес по маске /api/**/*
MODX предсказуемо выдаст событие onPageNotFound — ну а дальше как завещал @Василий Наумкин выстраиваем плагин маршрутизации — и делаем что захотим.
Это если решать все вопросы одним MODX. Да и тогда лучше использовать OnHandleRequest.

А так, лично я давно всё отправляю через Nginx:
location ~ ^/api/ {
    rewrite ^/api/(.*)$ /api.php?q=$1;
}
И там уже любые маршруты с контроллерами.
    Сергей Шлоков
    19 сентября 2019, 12:33
    0
    А Slim рекомендует так
    location ~ ^/api/ {
            try_files $uri /api/index.php$is_args$args;
        }
    Какое решение лучше?
      Василий Наумкин
      19 сентября 2019, 12:48
      1
      +1
      Это более общее правило. try_files проверяет, есть ли $uri на диске, как физический файл, и если нет — то шлёт запрос дальше, на общий роутер.

      У меня же конкретное правило — отправлять все запросы к /api сразу на api.php. Выходит, разница только в одной операции чтения диска, зато на каждый запрос.
    Сергей Шлоков
    19 сентября 2019, 09:43
    +6
    Выскажу здесь своё никому не нужное мнение.

    Интересная статья для размышления. Не хватает четвертого варианта, который описал Василий выше и который использую я при разработке RESTful API дополнения.
    Первые два варианта из разряда «забить гвоздь телефоном». Результат маленький и большие накладные расходы.
    Третий вариант — это взять маленький молоточек. Чтобы забить средние и большие гвозди придётся сильно попотеть.

    Цикл статей, имхо, нужен только для понимания, что встроенные средства MODX мало пригодны. Только для исключительно простых целей. Как по мне, даже JSON:API спецификация с его include, fields, filter и sort неудобна. Мне как разработчику было бы проще послать POST запрос, в котором описать как положено select, where, limit и т.п. Да, это уже не REST, но возможностей гораздо больше.
      Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
      4