События в модуле Bitrix
Модули могут взаимодействовать между собой двумя способами:
Явно
прямым вызовом исполняемого файлаСкрыто
через систему событий
Явное взаимодействие
Явное взаимодействие с помощью API. Подразумевает подключение модуля с помощью метода CModule:IncludeModule (), указав в качестве параметра id модуля с последующим непосредственным вызовом метода класса или функции модуля. Пример явного взаимодействия:
<?
// подключаем модуль
if (CModule::IncludeModule("mymodule"))
{
// выполним метод модуля
CMyModuleClass::DoIt();
}
Скрытное взаимодействие через события
Событие — это произвольное действие, в момент выполнения которого собираются все обработчики этого события и выполняются по одному. Обычно для регистрации событий в системе есть два метода RegisterModuleDependences
и AddEventHandler
.
Событие позволяет сделать модули максимально независимыми друг от друга. Модуль ничего не знает об особенностях функционирования другого модуля, но может взаимодействовать с ним через интерфейс событий.
Схема работы
Модуль, инициирующий событие, в том месте кода, где это событие происходит, должен как бы сообщить всей системе что событие наступило, это делается в два этапа:
- Собрать все зарегистрированные обработчики с помощью функции
GetModuleEvents
- Выполнить их по одному с помощью функции
ExecuteModuleEventEx
, обрабатывая соответствующим образом возвращаемые обработчиками значения
В свою очередь, модуль который хочет подписаться на событие другого модуля и выполнить какие-либо действие, должен:
- Зарегистрировать в момент инсталляции свой обработчик чужого события с помощью функции
RegisterModuleDependences
.RegisterModuleDependences
вызывается 1 раз за время работы проекта, например при установке модуля. Обработчик регистрируется в базе с указанием модуля, в котором определен обработчик. Срабатывание события, приведет к подключению модуля. Как следует из названия, эта функция регистрирует зависимости модуля. Ее стоит использовать когда вы разрабатываете свой модуль для битрикса. По сути вызов этого метода создает запись в таблицеb_module_to_module
- Добавить обработчик чужого события в глобальный массив, с помощью функции
AddEventHandler
который будет доступен в ходе выполнения программы и будет существовать только в рамках исполняемого скрипта, скрипт закончил исполнение, соответственно программа в целом забыла про событие.AddEventHandler
исполняется на каждом хите, дополняет массив обработчиков собранных из базы. Вот ссылка на документацию AddEventHandler
Пример взаимодействия
Ярким примером взаимодействия, является взаимодействие модулей системы с модулем Поиска
. Этот модуль не имеет никакой информации о данных других модулей, особенностях их хранения и обработки. Он только предоставляет интерфейс для индексации данных. Любой модуль системы, который должен индексироваться, при инсталляции регистрирует обработчик на событие OnReindex. Каждый такой обработчик в свою очередь возвращает данные для индексации, которые модуль Поиска
использует для наполнения своей базы.
Если быть проще, ниже приведен наглядный пример как это устроено.
Регистрация обработчика события, когда в модуле init_module
возникнет событие OnSomeEvent
, будет подключен модуль handler_module
, вызван класс CMyModuleClass::Handler
и метод BeforeIndex
:
install/index.php// заносим при инсталяции модуля в базу событие
function InstallEvents()
{
RegisterModuleDependences("init_module", "OnSomeEvent", "handler_module", "\\CMyModuleClass\\Handler", "BeforeIndex");
}
// удаляем при диинсталяции модуля из базы событие
function UnInstallEvents()
{
UnRegisterModuleDependences("init_module", "OnSomeEvent", "handler_module", "\\CMyModuleClass\\Handler", "BeforeIndex");
}
Генерация события, произвольная функция модуля init_module
в которой генерируется событие OnSomeEvent
:
// здесь располагается произвольный код представляющий из себя реализацию логики события
function MyFunction()
{
// собираем зарегистрированные через RegisterModuleDependences и AddEventHandler обработчики события OnSomeEvent
$rsHandlers = GetModuleEvents("init_module", "OnSomeEvent");
// перебираем зарегистрированные в системы события
while($arHandler = $rsHandlers->Fetch())
{
// выполняем каждое зарегистрированное событие по одному. Параметры могут передаваться как по ссылке так и по значению. Параметры переданные по значению могут быть изменены внутри обработчика. Для передачи параметра по значению в массив должна быть добавлена ссылка на него
ExecuteModuleEventEx($arHandler, array(/* массив параметров передаваемых в обработчики события */));
}
}
Обработчик события, класс и метод имеет следующие содержимое:
libs/eventhandler.phpnamespace CMyModuleClass;
class Handler
{
public static function BeforeIndex()
{
// код который должен выполнится
}
}