MORLIX JOURNAL
Как разработать модуль для CMS: жизненный цикл и API
Как спроектировать модуль CMS: API, установка и миграции, безопасность, тестирование и обновления.
Разработка модуля CMS начинается не с кнопки в админке, а с определения границ: какую задачу решает расширение, какие данные хранит, какие события обрабатывает и через какие официальные интерфейсы взаимодействует с системой. Установка, обновление, отключение и удаление — такие же важные части разработки, как пользовательская функция.
В этом материале разберём жизненный цикл и типичные точки интеграции на примере условного модуля заявок. Это архитектурный пример для разных CMS: названия методов, структура пакета и доступные события зависят от конкретной платформы. Перед реализацией сверяйтесь с её документацией и версией, а не копируйте псевдоинтерфейсы как готовый API.
Что такое модуль и где проходят его границы
Модуль добавляет самостоятельную возможность к системе управления: например, хранит заявки, предоставляет раздел администратору и отображает форму на сайте. В хорошо отделённой реализации ядро отвечает за общие сервисы и договорённости, а модуль использует публичные точки расширения. Такой подход облегчает обновления: изменение расширения не требует ручного редактирования файлов ядра.
Сначала опишите входы и выходы. Для заявок входом могут быть данные формы, выходом — запись в хранилище и уведомление ответственному. Укажите, кто имеет право просматривать заявки, какие настройки доступны владельцу, какие данные считаются персональными и что произойдёт при отключении расширения. Не собирайте поля, которые задаче не нужны.
Чтобы понять место модуля в системе, полезно сначала разобрать архитектуру CMS на PHP. На странице модулей Morlix можно посмотреть, как расширения представлены владельцу сайта. Общие принципы ниже не являются инструкцией к конкретному API Morlix.
Начните с контракта платформы
Изучите официальный способ регистрации расширения, поддерживаемые версии ядра и языка, правила именования и структуру пакета. Выясните, предоставляет ли CMS маршруты, события, систему прав, миграции и интерфейс хранения настроек. Если документация описывает стабильный публичный API, используйте его; внутренние классы и прямые изменения системных таблиц могут меняться без сохранения совместимости.
Составьте короткий контракт модуля: идентификатор и версию, зависимости, необходимые разрешения, точки входа, перечень хранимых данных и правила обновления. Для каждого внешнего API отдельно укажите формат ответа, ошибки и ограничения. Название события, сигнатуру обработчика или формат манифеста нельзя выводить из общих рассуждений: они должны быть подтверждены для выбранной CMS.

Жизненный цикл модуля
Установка
На этапе установки система обычно проверяет пакет и совместимость, регистрирует модуль и подготавливает необходимые ресурсы. Если модулю нужны таблицы или настройки, создавайте их через поддерживаемый механизм платформы. Начальные значения должны быть безопасными: например, внешняя отправка уведомлений не должна включаться до настройки адресата и проверки прав.
Установка может прерваться. Продумайте, как обнаружить частично созданные ресурсы, как безопасно повторить операцию и что записать в журнал. Не считайте установку успешной, если обязательная миграция завершилась ошибкой. Сохраняйте резервную копию перед изменениями структуры данных в рабочей системе.
Включение и обычная работа
При включении модуль подключает доступные ему маршруты, обработчики и интерфейс. В ходе запроса проверяются полномочия пользователя, затем данные проходят проверку и передаются в бизнес-логику. Логика хранения и отправки уведомлений не должна быть неразрывно привязана к HTML-шаблону: это упрощает тестирование и замену интерфейса.
Для условной заявки полезно разделить этапы: получить поля, проверить допустимые значения, сохранить запись и только затем инициировать уведомление. Если уведомление не дошло, необходимо различать сохранённую заявку и ошибку доставки. Повтор внешней отправки выполняйте только с учётом подтверждённого состояния, иначе пользователь может получить дубликаты.
Обновление
В новой версии может измениться схема данных или набор настроек. Храните версию схемы и применяйте последовательные миграции в порядке, поддерживаемом CMS. Проверяйте обновление не только с пустой установки, но и с предыдущих поддерживаемых версий, включая ситуацию с существующими записями.
Изменение формата API планируйте вместе с потребителями: какие поля обязательны, что произойдёт со старым клиентом, как сообщать об устаревании. Перед обновлением проверьте совместимость зависимостей и возможность восстановления из резервной копии. Не обещайте автоматический откат, если платформа его не обеспечивает.
Отключение и удаление
Отключение обычно должно прекращать работу расширения, не уничтожая созданные пользователем данные. Удаление требует отдельной политики: сохранить данные для последующей установки или удалить их по явному выбору администратора. Проверьте, что произойдёт с запланированными заданиями, подписками на события и внешними ключами доступа.
Документируйте различие между отключением и удалением заранее. Не удаляйте общие таблицы, файлы других расширений или данные сайта, которыми модуль не владеет. Если полная очистка предусмотрена, уточните её последствия и обеспечьте подтверждение точного действия.
Какие API и события могут понадобиться
Платформы различаются, но при проектировании полезно проверить несколько классов интерфейсов:
- Маршруты и контроллеры: как зарегистрировать страницу администрирования или публичную форму и проверить права до выполнения действия.
- События и хуки: где расширение может реагировать на событие CMS; что передаётся обработчику и какие ограничения действуют на побочные эффекты.
- Хранилище и миграции: как работать с базой, настройками и обновлением схемы без обхода механизмов платформы.
- Шаблоны и медиа: как выводить данные, экранировать их и использовать поддерживаемую библиотеку файлов.
- Очереди и фоновые задачи: как запускать длительную обработку, фиксировать ошибки и контролировать повторные попытки.
Это карта вопросов для разработчика, а не список гарантированных возможностей любой CMS. Если нужной точки расширения нет, не подменяйте её изменением ядра без оценки последствий. Сначала проверьте документированные альтернативы и договоритесь о границе ответственности между модулем и платформой.

Безопасность на каждом слое
Проверяйте права на сервере для каждого действия, включая чтение персональных заявок. Скрытая кнопка в интерфейсе не является проверкой доступа. Для действий, меняющих состояние, используйте защитные механизмы платформы, включая проверку подлинности запроса, где она предусмотрена.
Проверяйте входные данные по типу, длине и допустимым значениям; используйте параметризованные запросы к базе. При выводе пользовательского текста применяйте экранирование, соответствующее контексту вывода. Не доверяйте имени загруженного файла или только расширению: загрузки требуют отдельной проверки типа, размера, прав и места хранения.
Секреты интеграций не должны попадать в код, ссылки, журнал или публичные ответы API. Не записывайте содержимое заявок в диагностические логи без необходимости. Настройте хранение и доступ в соответствии с требованиями проекта и применимыми правилами обработки данных; при сомнениях привлекайте ответственного специалиста.
Пример проектирования: модуль заявок
Предположим, владелец сайта хочет получать обращения из формы. Минимальный первый выпуск: форма с необходимыми полями, серверная проверка, сохранение заявки и защищённый список для сотрудников. Уведомления можно добавить отдельно, когда определены адресат, очередь и правила повторов.
Проверьте сценарии до написания обработчиков: пустое обязательное поле, длинное сообщение, повторное нажатие отправки, отсутствие прав у сотрудника и ошибка хранилища. Решите, как пользователь узнает об успешном сохранении, не раскрывая лишние сведения. Для внешнего уведомления фиксируйте отдельный статус; не удаляйте заявку только потому, что почтовый сервис временно недоступен.
Для обновления запланируйте версионированное изменение схемы, например добавление необязательного поля с понятным значением для существующих записей. На тестовой копии проверьте старые данные до и после обновления. При удалении заранее определите, останутся ли заявки доступны и кто может подтвердить очистку.
Тестирование и выпуск
Проверяйте не только успешный сценарий. Нужны тесты на права, некорректный ввод, ошибки зависимостей и совместимость с заявленными версиями платформы. На тестовом окружении выполните чистую установку, настройку, отключение, повторное включение и обновление с предыдущей версии. Убедитесь, что данные пользователя сохранены согласно выбранной политике.
Добавьте проверку внешних интеграций на тайм-аут и неоднозначный ответ. Если сторонний сервис мог принять запрос до разрыва связи, слепой повтор небезопасен: используйте поддерживаемую идемпотентность или сверку состояния. Проверяйте журналы на отсутствие секретов и содержимого, которое не должно там храниться.
Перед выпуском подготовьте описание требований, инструкции по обновлению и удалению, список известных ограничений и порядок восстановления. На рабочем сайте сначала сделайте резервную копию и убедитесь, что она пригодна для восстановления. После установки проверьте статус модуля, ключевые действия и сообщения об ошибках.
Чек-лист разработчика
- Определена задача, границы данных и роли пользователей.
- Подтверждены версия платформы, зависимости и официальные точки расширения.
- Спроектированы установка, миграции, отключение и политика удаления.
- Права, проверка входных данных и безопасный вывод выполняются на сервере.
- Ошибки и повторные внешние запросы имеют понятное состояние без скрытых дублей.
- Проверены установка и обновление на копии с существующими данными.
- Подготовлены документация, резервное копирование и план восстановления.
Надёжный модуль — это не только функция, которая работает в идеальном сценарии. Он соблюдает контракт CMS, переживает обновления и ошибки, защищает данные и позволяет владельцу понять последствия своих действий. Начните с небольшой самостоятельной возможности и добавляйте интеграции после того, как её жизненный цикл проверен.