agentsclimarketplace

Bitrix events

Skill bxmaximum/bitrix-framework-skills/skills/bitrix-events

Covers Bitrix event system — new model (Bitrix\Main\Event, EventResult, EventManager::addEventHandler, make:event, make:eventhandler) and old model (OnBefore*/OnAfter* hooks in CIBlock, CUser, CSale and other classic APIs). Applied when integrating modules, entity lifecycle hooks, publishing custom events and subscribing to events of other modules. Key terms — Event, EventManager, EventResult, OnBefore, OnAfter, handler, subscriber, addEventHandler.From its SKILL.md

Install
npx -y skills add bxmaximum/bitrix-framework-skills --skill bitrix-events

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 19 stars19 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.0 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it

Bitrix Events

There are two event models: new (OOP, Event + EventResult) 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 (OnBeforeUserAdd, OnPageStart, ...).

New Model — Publishing Your Event

1. Create Event Class

php bitrix/bitrix.php make:event PostCreated -m vendor.blog

Since main 25.900 for make:*. On older versions, scaffold the class manually.

File: /local/modules/vendor.blog/lib/Public/Event/Post/PostCreatedEvent.php.

<?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

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()]);
    }
}

3. Write Handler

php bitrix/bitrix.php make:eventhandler NotifyAuthor \
    --event-module=vendor.blog --handler-module=vendor.notify

EventManager invokes handlers via call_user_func_array (class + method). Handlers are not created by ServiceLocator — do not rely on constructor DI. Resolve services inside the handler method.

<?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

\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 DoUninstall() — mandatory unRegisterEventHandler with the same parameters.

Old Model (Compatibility)

Old events have string names: OnBeforeUserAdd, OnAfterUserAdd, OnEpilog, OnPageStart. They pass an array/object of parameters and return:

  • true/nothing — continue;
  • false + $APPLICATION->ThrowException(...) — cancel action;
  • array with 'FIELDS' => [...] — modify fields (for OnBefore*).

Registering handlers accepting the old signature:

EventManager::getInstance()->registerEventHandlerCompatible(
    'main',
    'OnAfterUserAdd',
    'vendor.blog',
    \Vendor\Blog\Internals\Integration\Main\EventHandler\OnAfterUserAddHandler::class,
    'handle',
);

The new registerEventHandler also works with old events but adapts them to the Event $event signature — parameters are retrieved via $event->getParameter('fields'), modification via EventResult.

Order and Chain of Handlers

  • Handlers run in ascending $sort order (default 100).
  • addEventHandler($fromModuleId, $eventType, $callback, $includeFile = false, $sort = 100) — $sort is the 5th parameter.
  • registerEventHandler($fromModuleId, $eventType, $toModuleId, $toClass = '', $toMethod = '', $sort = 100, ...) — $sort is the 6th parameter.
  • The new API (Event::send()) collects results from all handlers — the chain is not interrupted even if one returns ERROR.
  • In the old API, a single false can interrupt the action (depends on the calling code in the kernel).

Dynamic Subscription in One Process

For hooks that don't need to be stored in the DB (tests, one-time wrappers):

EventManager::getInstance()->addEventHandler(
    'main',
    'OnAfterUserAdd',
    fn (array $fields) => /* ... */,
);

Such registration lives until the end of the request.

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\Event + EventResult instead of returning arrays.
  • Handler has no constructor DI — resolve services inside the method via ServiceLocator::get().
  • Handler is idempotent and does not crash — wrap everything in try/catch with logging.
  • Heavy logic is moved to a queue (Messenger via $message->send()), handler only dispatches a task.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.