Свой модуль - структура, установка, автозагрузка классов
Упаковываем код проекта в модуль: разбираем обязательные файлы, класс установки и то, что чаще всего забывают - удаление и обновление.
Решение
Собираем каталог модуля:
/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-блоки. Своя таблица - это ещё и своя миграция при обновлении.
Как обновлять модуль на боевом сайте?
Выкладкой файлов и скриптом обновления, который поднимает версию и правит данные. Переустановка ради обновления теряет настройки.
Где хранить страницу настроек?
В файле настроек модуля: платформа показывает её сама. Своя страница в административном разделе для этого не нужна.
Смежное
-
Class not found: причины по убыванию частоты - когда автозагрузка не находит класс модуля
-
Свой модуль - оглавление подтемы
-
Свой модуль или код в проекте: когда пора выносить в модуль - нужен ли модуль вообще
-
Форма в админке: вкладки, проверка значений, тулбар - страницы правки в административной части
-
Мастер тиражного решения: шаги, макросы, публичная часть - как решение разворачивает готовый сайт
-
Свой модуль не устанавливается: разбор причин - когда установка не проходит
-
Права в своём модуле: уровни, проверка, интерфейс настроек - свои уровни доступа у решения
-
Сторонняя библиотека в проекте: composer, автозагрузка, выкладка - сторонние библиотеки рядом со своим кодом
-
Обработчик события: регистрация, аргументы, отмена действия - что регистрирует установка
-
Своё действие бизнес-процесса: папка, описание, форма настроек - ещё один типовой житель решения
-
Свой тип пользовательского поля: регистрация, формы, значение - типовой житель модуля
-
Свой агент и задание по расписанию: создание, шаг, защита - фоновые задачи модуля
-
Call to undefined function: причины по убыванию частоты - когда автозагрузка модуля не сработала
-
Модули и решения - устройство модулей целиком
-
Git в проекте на платформе: состав репозитория и выкладка - как модуль попадает в репозиторий
-
Своя таблица на ORM: сущность, запросы, изменение структуры - что создаёт установка модуля
-
Свой компонент: когда нужен и из чего состоит - когда шаблона уже мало
-
Своя страница в админке: список, форма, пункт меню - интерфейс для данных модуля
-
Свои события в своём коде: как дать другим точку расширения - точки расширения своего решения
-
Настройки проекта: файл ядра, опции модуля, разные стенды - как хранить настройки модуля
-
Языковые файлы: сообщения, подстановки, второй язык - куда вынести тексты модуля
-
Готовое решение в проекте: установка, вмешательство, удаление - то же самое со стороны чужого кода
-
Composer и PSR-4: vendor, автозагрузка и Loader - сторонние библиотеки в модуле
-
Публикация своего модуля: требования, обновления, поддержка - если модуль пойдёт в продажу
-
Свои данные в поиске по сайту: индексация, адреса, права - как отдать данные модуля в общий поиск
-
Модуль установился, но не работает - разбор причин, если собранный модуль молчит