События в Yii2 — это мощный механизм, который позволяет расширять поведение классов без изменения их кода. Если вы когда-нибудь хотели добавить логирование, отправку уведомлений или другую реакцию на определённые действия, не влезая в чужой код, то события — ваш инструмент. В этой статье мы разберём, как устроены события в Yii2, как их правильно использовать и каких ошибок избегать.

Digital-студия WNDER

Что такое события и зачем они нужны

Представьте, что вы заказали пиццу. Вы не готовите её сами, но когда курьер звонит в дверь, вы совершаете действие — открываете дверь. В программировании событие — это сигнал о том, что что-то произошло. Класс-источник события (например, модель) сообщает: «Я сохранился!» или «Я удалился!». Другие части программы могут «подписаться» на это событие и выполнить свой код.

В Yii2 события реализованы через механизм Event и EventDispatcher. Основные компоненты: источник события (класс, который наследует yii\base\Component), имя события и обработчик (callback-функция).

Как привязать обработчик к событию

Самый простой способ — использовать метод on() у компонента. Например, у нас есть модель Order, и мы хотим после её сохранения отправить письмо.


// В контроллере или конфигурации
$order = new Order();
$order->on(Order::EVENT_AFTER_INSERT, function ($event) {
    // Отправляем письмо
    Yii::$app->mailer->compose()
        ->setTo('client@example.com')
        ->setSubject('Заказ оформлен')
        ->send();
});
$order->save();

Здесь EVENT_AFTER_INSERT — это константа, определённая в модели. Yii2 предоставляет множество встроенных событий для ActiveRecord: EVENT_BEFORE_INSERT, EVENT_AFTER_INSERT, EVENT_BEFORE_UPDATE, EVENT_AFTER_UPDATE, EVENT_BEFORE_DELETE, EVENT_AFTER_DELETE и другие.

Если нужно отвязать обработчик, используйте off().

Продвинутый уровень: глобальные события и EventDispatcher

В больших приложениях удобно использовать глобальный диспетчер событий. Yii2 предлагает класс yii\base\Event и компонент yii\base\EventDispatcher (доступен с версии 2.0.14). Он позволяет подписываться на события по имени класса и имени события, не создавая экземпляр.


// Подписка на событие класса Order
Yii::$app->eventDispatcher->on(Order::class, Order::EVENT_AFTER_INSERT, function ($event) {
    // Обработчик
});

// Генерация события в модели
$this->trigger(Order::EVENT_AFTER_INSERT);

Такой подход удобен для модулей и расширений: вы не привязываетесь к конкретному экземпляру.

Практические советы и лайфхаки

Правило: Всегда проверяйте, не отключено ли событие. Используйте $event->isValid в обработчиках before-событий, чтобы можно было отменить операцию.

Вот несколько проверенных приёмов:

  • Именуйте события осмысленно. Используйте константы, например EVENT_USER_REGISTERED, а не просто строки.
  • Не злоупотребляйте событиями. Если логика тесно связана с классом, лучше переопределить метод, а не вешать обработчик.
  • Используйте слабую связность. Обработчики не должны зависеть от конкретных экземпляров, если это возможно.
  • Документируйте события. В коде класса указывайте, какие события он генерирует и что передаётся в объекте события.

Сравним основные методы для работы с событиями:

Метод Где используется Описание
on() Экземпляр компонента Привязывает обработчик к событию конкретного объекта
off() Экземпляр компонента Отвязывает обработчик
trigger() Внутри класса Генерирует событие
EventDispatcher::on() Глобально Подписка на события класса без экземпляра

Типичные ошибки и как их избежать

Новички часто наступают на одни и те же грабли. Вот самые распространённые:

  • Забывают про порядок выполнения. Обработчики вызываются в порядке добавления. Если важен порядок, указывайте его явно.
  • Изменяют данные в after-событиях. После сохранения модели изменения не попадут в базу. Используйте before-события для модификации атрибутов.
  • Создают циклические зависимости. Обработчик одного события может генерировать другое, что приведёт к бесконечному циклу. Будьте осторожны.
Лайфхак: Для отладки событий можно временно добавить логирование в обработчик или использовать компонент yii\debug\Panels\EventPanel (входит в yii2-debug). Он покажет все сгенерированные события и их обработчики.

Что в итоге

События в Yii2 — это элегантный способ сделать код расширяемым и слабосвязанным. Используйте их для реакций на действия, но не заменяйте ими основную логику. Помните о порядке обработчиков, документируйте события и не забывайте про отмену операций через $event->isValid. И тогда ваш код станет чище, а жизнь — проще.

Студия WNDER