← К документации

Модули

События в модуле

Рабочая справка по событиям в локальном модуле Bitrix: регистрация при установке, удаление обработчиков, CRM-события, OnProlog и ORM-события.

События лучше регистрировать при установке модуля и удалять при удалении. Не нужно каждый раз добавлять обработчики в include.php без необходимости.

В примерах ниже CRM и main передают старые аргументы события, поэтому постоянная регистрация выполняется через registerEventHandlerCompatible. Для собственного D7-события с объектом Event выбирается обычный метод.

Общее понимание

События позволяют модулю реагировать на действия ядра, 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->registerEventHandlerCompatible(
            'crm',
            'OnAfterCrmDealUpdate',
            $this->MODULE_ID,
            \test\Example\EventHandler\CrmDealHandler::class,
            'onAfterDealUpdate'
        );

        $event_manager->registerEventHandlerCompatible(
            '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,
                'field_names' => array_keys($deal_fields),
            ],
            'test_example'
        );
    }
}

Если обработчик внутри себя меняет ту же сделку, добавь защиту от повторного запуска.

Событие OnProlog

<?php

namespace test\Example\EventHandler;

use Bitrix\Main\Context;
use Bitrix\Main\Page\Asset;

class AssetHandler {
    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;
    }
}

Источники