Перейти к содержимому

Свой модуль - структура, установка, автозагрузка классов

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

Решение

Собираем каталог модуля:

Окно терминала
/home/bitrix/www/local/modules/vendor.shop/
├── include.php # подключается при загрузке модуля
├── install/index.php # класс установки, без него модуля нет в списке
├── lib/sync.php # классы модуля, находятся автозагрузкой
├── lang/ru/install/index.php # названия и подписи модуля на русском
└── options.php # страница настроек в административной части

Платформа узнаёт модуль по имени каталога и по классу установки. Имя составное: до точки - автор, после - решение, и это же имя дальше служит идентификатором в настройках и правах.

Пишем класс установки:

class vendor_shop extends CModule
{
public $MODULE_ID = 'vendor.shop'; // имя каталога и ключ настроек
public $MODULE_VERSION = '1.0.0'; // версия видна в списке модулей
public function DoInstall() {
RegisterModule($this->MODULE_ID); // модуль появляется в списке
// здесь же создают свои таблицы и копируют файлы в публичную часть
RegisterModuleDependences('sale', 'OnSaleOrderSaved', $this->MODULE_ID,
'\\Vendor\\Shop\\Handlers', 'onOrderSaved');
}
}

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

Не забываем удаление:

public function DoUninstall() {
UnRegisterModuleDependences('sale', 'OnSaleOrderSaved', $this->MODULE_ID,
'\\Vendor\\Shop\\Handlers', 'onOrderSaved');
UnRegisterModule($this->MODULE_ID);
// таблицы сносим только с согласия администратора, а не молча
}

Удаление снимает ровно то, что до этого поставила установка. Забытая отмена регистрации оставляет мёртвый обработчик, который платформа пытается вызывать после удаления модуля и роняет сохранение заказа.

Храним настройки в настройках, а не в файлах:

\Bitrix\Main\Config\Option::set('vendor.shop', 'api_key', $key);
$key = \Bitrix\Main\Config\Option::get('vendor.shop', 'api_key', '');
// третий аргумент - значение по умолчанию для чистой установки
// значения переживают выкладку новой версии модуля
// чужие решения из каталога устроены ровно так же, включая эти методы
// имя модуля с точкой обязательно: по нему платформа ищет каталог решения

Настройки, записанные в файлы модуля, затираются при выкладке новой версии. Хранение по идентификатору модуля решает это и заодно даёт готовую страницу настроек в административной части.

Версию модуля поднимают при каждой новой выкладке. Она видна в списке модулей и отвечает на первый вопрос при разборе: «а какая версия стоит на боевом сайте».

Модуль стоит заводить сразу, а не после третьей правки файла обработчиков. Перенос разросшегося кода в модуль задним числом означает разбор зависимостей и проверку всего, что успело на него опереться.

Модуль стоит заводить сразу, а не после третьей правки файла обработчиков. Перенос разросшегося кода в модуль задним числом означает разбор зависимостей и проверку всего, что успело на него опереться.

Классы находятся автозагрузкой по имени файла и пространству имён. Ручные подключения файлов внутри модуля - признак того, что правило именования нарушено, и обычно это чинится переименованием.

Типичные проблемы

Модуля нет в списке для установки.

Отсутствует класс установки либо имя класса не совпадает с именем каталога. Платформа ищет модуль именно по этой паре и другого способа не знает.

После удаления модуля сайт падает при сохранении заказа.

Обработчик не снят с регистрации при удалении модуля. Платформа продолжает вызывать класс, которого больше нет.

Настройки сбросились после выкладки.

Значения хранились в файле внутри самого модуля. Выкладка новой версии перезаписала этот файл вместе с ними.

Классы модуля не находятся.

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

После обновления платформы модуль исчез.

Он лежал рядом со штатными модулями, а не в каталоге для своих. Обновление возвращает штатный каталог к исходному виду вместе с содержимым.

Частые вопросы

Чем модуль лучше файла с обработчиками?

Он ставится и снимается целиком, знает свою версию и переносится на другой проект. Файл обработчиков растёт и не переносится.

Нужны ли модулю свои таблицы?

Только если данные не ложатся в инфоблоки и highload-блоки. Своя таблица - это ещё и своя миграция при обновлении.

Как обновлять модуль на боевом сайте?

Выкладкой файлов и скриптом обновления, который поднимает версию и правит данные. Переустановка ради обновления теряет настройки.

Где хранить страницу настроек?

В файле настроек модуля: платформа показывает её сама. Своя страница в административном разделе для этого не нужна.

Смежное

Первоисточник