bitrix-events
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBitrix Events
Bitrix 事件
There are two event models: new (OOP, + ) and old (string code + handler returning bool/array). For new code — use the new model. The old model is used for compatibility with the kernel (, , ...).
EventEventResultOnBeforeUserAddOnPageStartBitrix 包含两种事件模型:新模型(面向对象, + )和旧模型(字符串代码 + 返回布尔值/数组的handler)。新代码建议使用新模型,旧模型仅用于与内核兼容(如、等)。
EventEventResultOnBeforeUserAddOnPageStartNew Model — Publishing Your Event
新模型——发布自定义事件
1. Create Event Class
1. 创建事件类
bash
php bitrix/bitrix.php make:event PostCreated -m vendor.blogSince main 25.900 for . On older versions, scaffold the class manually.
make:*File: .
/local/modules/vendor.blog/lib/Public/Event/Post/PostCreatedEvent.phpphp
<?php declare(strict_types=1);
namespace Vendor\Blog\Public\Event\Post;
use Bitrix\Main\Event;
final class PostCreatedEvent extends Event
{
public function __construct(
public readonly int $postId,
public readonly int $authorId,
public readonly string $title,
) {
parent::__construct('vendor.blog', self::class, [
'postId' => $this->postId,
'authorId' => $this->authorId,
'title' => $this->title,
]);
}
}bash
php bitrix/bitrix.php make:event PostCreated -m vendor.blogmake:*文件路径:。
/local/modules/vendor.blog/lib/Public/Event/Post/PostCreatedEvent.phpphp
<?php declare(strict_types=1);
namespace Vendor\Blog\Public\Event\Post;
use Bitrix\Main\Event;
final class PostCreatedEvent extends Event
{
public function __construct(
public readonly int $postId,
public readonly int $authorId,
public readonly string $title,
) {
parent::__construct('vendor.blog', self::class, [
'postId' => $this->postId,
'authorId' => $this->authorId,
'title' => $this->title,
]);
}
}2. Dispatch Event from Service
2. 从服务中触发事件
php
use Vendor\Blog\Public\Event\Post\PostCreatedEvent;
$event = new PostCreatedEvent($post->getId(), $post->getAuthorId(), $post->getTitle());
$event->send();
foreach ($event->getResults() as $result)
{
if ($result->getType() === \Bitrix\Main\EventResult::ERROR)
{
$this->logger->warning('Subscriber failed', ['errors' => $result->getParameters()]);
}
}php
use Vendor\Blog\Public\Event\Post\PostCreatedEvent;
$event = new PostCreatedEvent($post->getId(), $post->getAuthorId(), $post->getTitle());
$event->send();
foreach ($event->getResults() as $result)
{
if ($result->getType() === \Bitrix\Main\EventResult::ERROR)
{
$this->logger->warning('Subscriber执行失败', ['errors' => $result->getParameters()]);
}
}3. Write Handler
3. 编写处理器
bash
php bitrix/bitrix.php make:eventhandler NotifyAuthor \
--event-module=vendor.blog --handler-module=vendor.notifyEventManager invokes handlers via (class + method). Handlers are not created by — do not rely on constructor DI. Resolve services inside the handler method.
call_user_func_arrayServiceLocatorphp
<?php declare(strict_types=1);
namespace Vendor\Notify\Internals\Integration\Blog\EventHandler;
use Bitrix\Main\DI\ServiceLocator;
use Bitrix\Main\Event;
use Bitrix\Main\EventResult;
use Vendor\Blog\Public\Event\Post\PostCreatedEvent;
use Vendor\Notify\Application\Service\Notifier;
final class NotifyAuthorHandler
{
public static function handle(Event $event): EventResult
{
if (!$event instanceof PostCreatedEvent)
{
return new EventResult(EventResult::UNDEFINED);
}
/** @var Notifier $notifier */
$notifier = ServiceLocator::getInstance()->get(Notifier::class);
$result = $notifier->notifyAuthor($event->authorId, $event->title);
return new EventResult(
$result->isSuccess() ? EventResult::SUCCESS : EventResult::ERROR,
$result->getErrorMessages(),
);
}
}bash
php bitrix/bitrix.php make:eventhandler NotifyAuthor \
--event-module=vendor.blog --handler-module=vendor.notifyEventManager 通过 (类+方法)调用处理器。处理器不会由创建——不要依赖构造函数注入,需在处理器方法内部解析服务。
call_user_func_arrayServiceLocatorphp
<?php declare(strict_types=1);
namespace Vendor\Notify\Internals\Integration\Blog\EventHandler;
use Bitrix\Main\DI\ServiceLocator;
use Bitrix\Main\Event;
use Bitrix\Main\EventResult;
use Vendor\Blog\Public\Event\Post\PostCreatedEvent;
use Vendor\Notify\Application\Service\Notifier;
final class NotifyAuthorHandler
{
public static function handle(Event $event): EventResult
{
if (!$event instanceof PostCreatedEvent)
{
return new EventResult(EventResult::UNDEFINED);
}
/** @var Notifier $notifier */
$notifier = ServiceLocator::getInstance()->get(Notifier::class);
$result = $notifier->notifyAuthor($event->authorId, $event->title);
return new EventResult(
$result->isSuccess() ? EventResult::SUCCESS : EventResult::ERROR,
$result->getErrorMessages(),
);
}
}4. Register Handler in install/index.php
install/index.php4. 在install/index.php
中注册处理器
install/index.phpphp
\Bitrix\Main\EventManager::getInstance()->registerEventHandler(
fromModule: 'vendor.blog',
eventType: \Vendor\Blog\Public\Event\Post\PostCreatedEvent::class,
toModuleId: 'vendor.notify',
toClass: \Vendor\Notify\Internals\Integration\Blog\EventHandler\NotifyAuthorHandler::class,
toMethod: 'handle',
);In — mandatory with the same parameters.
DoUninstall()unRegisterEventHandlerphp
\Bitrix\Main\EventManager::getInstance()->registerEventHandler(
fromModule: 'vendor.blog',
eventType: \Vendor\Blog\Public\Event\Post\PostCreatedEvent::class,
toModuleId: 'vendor.notify',
toClass: \Vendor\Notify\Internals\Integration\Blog\EventHandler\NotifyAuthorHandler::class,
toMethod: 'handle',
);在方法中——必须使用相同参数调用来注销处理器。
DoUninstall()unRegisterEventHandlerOld Model (Compatibility)
旧模型(兼容模式)
Old events have string names: , , , . They pass an array/object of parameters and return:
OnBeforeUserAddOnAfterUserAddOnEpilogOnPageStart- /nothing — continue;
true - +
false— cancel action;$APPLICATION->ThrowException(...) - array with — modify fields (for
'FIELDS' => [...]).OnBefore*
Registering handlers accepting the old signature:
php
EventManager::getInstance()->registerEventHandlerCompatible(
'main',
'OnAfterUserAdd',
'vendor.blog',
\Vendor\Blog\Internals\Integration\Main\EventHandler\OnAfterUserAddHandler::class,
'handle',
);The new also works with old events but adapts them to the signature — parameters are retrieved via , modification via .
registerEventHandlerEvent $event$event->getParameter('fields')EventResult旧事件使用字符串名称:、、、。它们传递参数数组/对象,并返回以下结果:
OnBeforeUserAddOnAfterUserAddOnEpilogOnPageStart- /无返回值——继续执行;
true - +
false——取消操作;$APPLICATION->ThrowException(...) - 包含的数组——修改字段(适用于
'FIELDS' => [...]事件)。OnBefore*
注册支持旧签名的处理器:
php
EventManager::getInstance()->registerEventHandlerCompatible(
'main',
'OnAfterUserAdd',
'vendor.blog',
\Vendor\Blog\Internals\Integration\Main\EventHandler\OnAfterUserAddHandler::class,
'handle',
);新的也可用于旧事件,但会将其适配为签名——参数需通过获取,字段修改需通过实现。
registerEventHandlerEvent $event$event->getParameter('fields')EventResultOrder and Chain of Handlers
处理器的执行顺序与调用链
- Handlers run in ascending order (default
$sort).100 - —
addEventHandler($fromModuleId, $eventType, $callback, $includeFile = false, $sort = 100)is the 5th parameter.$sort - —
registerEventHandler($fromModuleId, $eventType, $toModuleId, $toClass = '', $toMethod = '', $sort = 100, ...)is the 6th parameter.$sort - The new API () collects results from all handlers — the chain is not interrupted even if one returns
Event::send().ERROR - In the old API, a single can interrupt the action (depends on the calling code in the kernel).
false
- 处理器按值升序执行(默认值为100)。
$sort - ——
addEventHandler($fromModuleId, $eventType, $callback, $includeFile = false, $sort = 100)是第5个参数。$sort - ——
registerEventHandler($fromModuleId, $eventType, $toModuleId, $toClass = '', $toMethod = '', $sort = 100, ...)是第6个参数。$sort - 新API()会收集所有处理器的结果——即使某个处理器返回
Event::send(),调用链也不会中断。ERROR - 在旧API中,单个返回值可能会中断操作(取决于内核中的调用代码)。
false
Dynamic Subscription in One Process
单进程内动态订阅
For hooks that don't need to be stored in the DB (tests, one-time wrappers):
php
EventManager::getInstance()->addEventHandler(
'main',
'OnAfterUserAdd',
fn (array $fields) => /* ... */,
);Such registration lives until the end of the request.
适用于无需存储到数据库的钩子(如测试、一次性包装器):
php
EventManager::getInstance()->addEventHandler(
'main',
'OnAfterUserAdd',
fn (array $fields) => /* ... */,
);此类注册仅在当前请求周期内有效。
Checklist
检查清单
- Public event files — in .
/lib/Public/Event/<Aggregate>/ - Handlers of other modules' events — in .
/lib/Internals/Integration/<OtherModule>/EventHandler/ - Registration and unregistration of handlers as a pair in /
DoInstall.DoUninstall - Custom events use +
Bitrix\Main\Eventinstead of returning arrays.EventResult - Handler has no constructor DI — resolve services inside the method via .
ServiceLocator::get() - Handler is idempotent and does not crash — wrap everything in with logging.
try/catch - Heavy logic is moved to a queue (via
Messenger), handler only dispatches a task.$message->send()
- 公共事件文件存放于目录。
/lib/Public/Event/<Aggregate>/ - 其他模块事件的处理器存放于目录。
/lib/Internals/Integration/<OtherModule>/EventHandler/ - 处理器的注册与注销需在/
DoInstall中配对实现。DoUninstall - 自定义事件使用+
Bitrix\Main\Event,而非返回数组。EventResult - 处理器不依赖构造函数注入——需通过在方法内部解析服务。
ServiceLocator::get() - 处理器需保证幂等性且不会崩溃——使用包裹逻辑并添加日志。
try/catch - 重逻辑需转移到队列(通过调用
$message->send()),处理器仅负责分发任务。Messenger