Модули
События в модуле
Рабочая справка по событиям в локальном модуле Bitrix: регистрация при установке, удаление обработчиков, CRM-события, OnProlog и ORM-события.
События лучше регистрировать при установке модуля и удалять при удалении. Не стоит каждый
раз добавлять обработчики в include.php без необходимости.
Общее понимание
События позволяют модулю реагировать на действия ядра, CRM, ORM и других модулей.
Какие бывают события
| Тип | Пример | Когда использовать |
|---|---|---|
| События ядра | OnProlog, OnEpilog | Подключение JS/CSS, общая логика на страницах. |
| События CRM | OnAfterCrmDealUpdate | Реакция на изменение сделок, лидов, контактов, компаний. |
| ORM-события | OnBeforeAdd, OnAfterUpdate | Логика вокруг своих ORM-таблиц. |
| Свои события | OnAfterExampleSync | Когда модуль должен дать точку расширения для другого кода. |
Где регистрировать
Постоянные обработчики удобно регистрировать в installEvents() установщика
и удалять в uninstallEvents(). Временные обработчики на один хит можно
добавлять через addEventHandler(), но это другой сценарий.
Регистрация событий
Пример регистрации обработчиков в установщике модуля.
installEvents
<?php
use Bitrix\Main\EventManager;
class test_example extends CModule
{
public $MODULE_ID = 'test.example';
/**
* Регистрирует обработчики событий.
*/
public function installEvents(): bool
{
$event_manager = EventManager::getInstance();
$event_manager->registerEventHandler(
'crm',
'OnAfterCrmDealUpdate',
$this->MODULE_ID,
\test\Example\EventHandler\CrmDealHandler::class,
'onAfterDealUpdate'
);
$event_manager->registerEventHandler(
'main',
'OnProlog',
$this->MODULE_ID,
\test\Example\EventHandler\AssetHandler::class,
'onProlog'
);
return true;
}
} uninstallEvents
<?php
use Bitrix\Main\EventManager;
class test_example extends CModule
{
public $MODULE_ID = 'test.example';
/**
* Удаляет обработчики событий.
*/
public function uninstallEvents(): bool
{
$event_manager = EventManager::getInstance();
$event_manager->unRegisterEventHandler(
'crm',
'OnAfterCrmDealUpdate',
$this->MODULE_ID,
\test\Example\EventHandler\CrmDealHandler::class,
'onAfterDealUpdate'
);
$event_manager->unRegisterEventHandler(
'main',
'OnProlog',
$this->MODULE_ID,
\test\Example\EventHandler\AssetHandler::class,
'onProlog'
);
return true;
}
} Класс обработчика
Обработчики удобно хранить отдельно в lib/EventHandler.
/local/modules/test.example/lib/EventHandler/
├── CrmDealHandler.php
└── AssetHandler.php Не забудь зарегистрировать эти классы в автозагрузке модуля.
Примеры
Несколько типовых обработчиков, которые часто нужны в локальных модулях.
Событие CRM
<?php
namespace test\Example\EventHandler;
class CrmDealHandler
{
/**
* Обрабатывает изменение сделки.
*/
public static function onAfterDealUpdate(array &$deal_fields): void
{
$deal_id = isset($deal_fields['ID']) ? (int) $deal_fields['ID'] : 0;
if ($deal_id <= 0) {
return;
}
AddMessage2Log(
[
'message' => 'Сделка изменена',
'deal_id' => $deal_id,
'fields' => $deal_fields,
],
'test_example'
);
}
} Если обработчик внутри себя меняет ту же сделку, добавь защиту от повторного запуска.
Событие OnProlog
<?php
namespace test\Example\EventHandler;
use Bitrix\Main\Context;
use Bitrix\Main\Page\Asset;
class AssetHandler
{
/**
* Подключает ресурсы модуля на страницах CRM.
*/
public static function onProlog(): void
{
$request_uri = (string) Context::getCurrent()->getRequest()->getRequestUri();
if (strpos($request_uri, '/crm/') === false) {
return;
}
Asset::getInstance()->addCss('/local/css/test.example/app.css');
Asset::getInstance()->addJs('/local/js/test.example/app.js');
}
} ORM-событие
Для своей ORM-таблицы можно описать методы событий прямо в Table-классе.
<?php
namespace test\Example\Model;
use Bitrix\Main\Entity;
use Bitrix\Main\ORM\Event;
use Bitrix\Main\ORM\EventResult;
use Bitrix\Main\ORM\Fields;
class ExampleTable extends Entity\DataManager
{
/**
* Возвращает имя таблицы.
*/
public static function getTableName(): string
{
return 'b_test_example_item';
}
/**
* Возвращает карту полей.
*/
public static function getMap(): array
{
return [
new Fields\IntegerField('ID', [
'primary' => true,
'autocomplete' => true,
]),
new Fields\StringField('TITLE'),
];
}
/**
* Проверяет данные перед добавлением.
*/
public static function onBeforeAdd(Event $event): EventResult
{
$result = new EventResult();
$fields = $event->getParameter('fields');
if (empty($fields['TITLE'])) {
$result->addError(
new Entity\FieldError(
static::getEntity()->getField('TITLE'),
'Название не заполнено'
)
);
}
return $result;
}
}