
События связаны с таким понятием как "поведения", про которые почитать можно тут.
События можно создавать свои, но чаще используют встроенные в фреймворк:
Yii2-события для MVC Веб-представление, которое наследуется от yii\web\View EVENT_BEGIN_BODY EVENT_END_BODY Model EVENT_AFTER_VALIDATE EVENT_BEFORE_VALIDATE Module или Controller EVENT_AFTER_ACTION - afterAction EVENT_BEFORE_ACTION - beforeAction Компонент представления yii\base\View EVENT_AFTER_RENDER EVENT_BEFORE_RENDER EVENT_END_PAGE EVENT_BEGIN_PAGE Cвязанные с БД yii\db\BaseActiveRecord EVENT_INIT EVENT_AFTER_FIND EVENT_BEFORE_INSERT (перед сохранением данных в БД) EVENT_AFTER_INSERT EVENT_BEFORE_UPDATE EVENT_AFTER_UPDATE EVENT_BEFORE_DELETE EVENT_AFTER_DELETE yii\db\ActiveQuery EVENT_INIT yii\db\Connection EVENT_AFTER_OPEN (наступает после подключения к БД) EVENT_BEGIN_TRANSACTION EVENT_COMMIT_TRANSACTION EVENT_ROLLBACK_TRANSACTION Yii2-события уровня запросов yii\base\Application EVENT_BEFORE_REQUEST - beforeRequest EVENT_AFTER_REQUEST - afterRequest yii\web\Response EVENT_BEFORE_SEND EVENT_AFTER_SEND EVENT_AFTER_PREPARE Yii2-события для компонентов по умолчанию yii\i18n\MessageSource EVENT_MISSING_TRANSLATION yii\mail\BaseMailer EVENT_BEFORE_SEND EVENT_AFTER_SEND yii\web\User События связанные с авторизацией EVENT_BEFORE_LOGIN EVENT_AFTER_LOGIN EVENT_BEFORE_LOGOUT EVENT_AFTER_LOGOUT
Привязку событий к определенному объекту/классу можно осуществлять:
- в методах объектов и классов;
- в конфигурации приложения.
Установка обработчиков событий в методах объектов и классов.
Для примеров использую экземпляр класса PostController, который наследует от класса Controller. А код примеров рассчитан на выполнение из действия данного контроллера.Обработчик - глобальная функция
$obj->on(Class::EVENT_HELLO, 'function_name');
Например в контроллере – после выполнения данного действия вызывается функция get_hello() пользовательского компонента «comp» (класс comp подключен в файле config\main.php в массиве components)
$this->on(yii\web\Controller::EVENT_AFTER_ACTION, Yii::$app->comp->get_hello());
Обработчик - метод объекта
$obj->on(Class::EVENT_HELLO, [$object, 'methodName']);
Например в контроллере – после выполнения данного действия вызывается другой метод контроллера fun_test()
$this->on(yii\web\Controller::EVENT_AFTER_ACTION, [$this, 'fun_test']);
Обработчик - метод класса
$obj->on(Class::EVENT_HELLO, ['app\components\Bar', 'methodName']);
Например в контроллере – после выполнения действия вызывается метод name() из класса Slug.
$this->on(yii\web\Controller::EVENT_AFTER_ACTION, ['common\behaviors\Slug', 'name']);
$obj->on(Class::EVENT_HELLO, function ($event) {}
Например в контроллере – после выполнения действия меняется значение публичной переменной text.
$this->on(yii\web\Controller::EVENT_AFTER_ACTION, function ($event) { if($this->text == 'Привет') $this->text = 'Приветствую!'; });
Установка обработчиков событий в конфигурации приложения.
В конфигурации привязку событий можно указывать 2-мя способами:
или
Во втором случае нужно явно указывать объект к которому оно привязывается.
Например компонент 'comp' с классом common\components\Comp:
'comp' => [ 'class' => 'common\components\Comp', 'age' => 23, 'on '. \yii\db\ActiveRecord::EVENT_INIT => function ($event) { или тоже самое: 'on init' => function ($event) { }, ],в данном примере класс Comp должен наследоваться от ActiveRecord или дочернего его класса:
class Comp extends \common\models\Post{}тогда событие сработает, т.к. оно срабатывает при самом наследовании (инициализации) от ActiveRecord.
$config['on afterAction'] = function ($event) { \app\components\GoogleAnalytics::collect(); };Тут, для примера, вызывается статический метод collect класса GoogleAnalytics.
Установка событий до запуска приложения.
Можно назначить разные обработчики событий в процессе начальной загрузки приложения.Покажу на примере события для действия контроллера.
Можно разместить в массиве retur (не в components) в файле main.php:
'on afterAction' => function () { exit('Событие после выполнения действия контроллера.'); },
Или разместить в файле web\index.php сразу после того как приложение будет создано (перед строкой $application->run())
Yii::$app->on('afterAction', function ($event) { exit('Событие после выполнения действия контроллера.'); });
События для самого приложения (Yii::$app).
Тут у нас 2 стандартных события Yii2:EVENT_BEFORE_REQUEST - beforeRequest
EVENT_AFTER_REQUEST - afterRequest
Аналогично разделу выше - можно назначить обработчики событий в процессе начальной загрузки приложения, сразу после того как приложение будет создано. Пример аналогичный, меняется только название действия.
В файле main.php:
'on beforeRequest' => function () { exit('Остановка перед запуском приложения.'); },
Или в web\index.php перед строкой $application->run()
\Yii::$app->on(\yii\base\Application::EVENT_BEFORE_REQUEST, function ($event) { exit('Остановка перед запуском приложения.'); });
Порядок обработки событий.
К одному событию можно присоединить несколько обработчиков. При срабатывании события обработчики будут вызываться в том порядке, к котором они присоединялись к событию.Чтобы запретить в обработчике вызов всех следующих за ним обработчиков, необходимо установить свойство [[yii\base\Event::handled]] параметра $event в true:
$foo->on(Foo::EVENT_HELLO, function ($event) { $event->handled = true; });
Чтобы обработчик присоединился к началу очереди и запускался первым, при вызове [[yii\base\Component::on()]] в качестве четвертого параметра $append следует передать false:
$foo->on(Foo::EVENT_HELLO, function ($event) { // ... }, $data, false);
Отсоединение обработчиков событий.
Для отсоединения обработчика от события используется метод [[yii\base\Component::off()]].Устанавливается аналогично методу on().
Чтобы отсоединить ВСЕ обработчики от события:
$obj->off(Class::EVENT_HELLO);
$this->off(yii\web\Controller::EVENT_AFTER_ACTION);

Инициирование событий (создание своих).
Класс, в котором инициируются события, должен наследовать от [[yii\base\Component]] или потомка этого класса.
Пример.
Создаем свой класс и подключаем его как компонент в файле config\main.php в массиве components
<?php namespace common\components; use yii\base\Component; use yii\base\Event; class Comp extends Component { const EVENT_HELLO = 'hello'; public function bar() { $this->trigger(self::EVENT_HELLO); //инициирование события /* * Основной функционал метода */ } public function linking(){ $this->on(self::EVENT_HELLO, function ($event) { exit('Привет!'); }); } }Показанный выше код инициирует событие hello при каждом вызове метода bar(). Событие привязывается в методе linking(). Поэтому вначале должен быть выполнен данный метод.
Использование:
<div>//Привязываем свой обработчик в этом методе Yii::$app->comp->linking();</div><div> //Вызываем метод который инициирует событие Yii::$app->comp->bar(); //Привет!</div>
Привязку события можно производить в любом месте (не нужен метод linking()), например в действии контроллера:
Yii::$app->comp->on(\common\components\Comp::EVENT_HELLO, function ($event) { exit('Привет!'); }); Yii::$app->comp->bar();
Если нужна привязка для всех объектов данного класса, то удобно применять специальный метод __construct() (добавить в класс) для того, чтобы не вызывать отдельно метод привязывающий событие.
public function __construct(){ parent::__construct(); $this->on(self::EVENT_HELLO, function ($event) { exit('Привет!'); }); }
Обработчики событий на уровне класса.
В примерах выше, обработчики событий привязывались к определенному объекту (экземпляру класса) и при создании нового экземпляра необходимо было бы привязывать обработчики снова (если не применять специальный метод __construct()).Если нужно вызывать событие для каждого экземпляра класса, а привязку сделать за его пределами – применяется статический метод [[yii\base\Event::on()]].
Пример раздела «Инициирование событий» при этом будет выглядеть так:
<?php namespace common\components; use yii\base\Component; use yii\base\Event; class Comp extends Component { const EVENT_HELLO = 'hello'; public function bar() { $this->trigger(self::EVENT_HELLO); //инициирование события /* * Основной функционал метода */ } }
Привязка ко всем экземплярам класса за пределами класса выглядит так:
\yii\base\Event::on(\common\components\Comp::className(), \common\components\Comp::EVENT_HELLO, function ($event) { exit('Привет!'); });
Теперь при создании любого экземпляра класса сработает событие при вызове метода его инициирующего.
$new_comp1 = new \common\components\Comp(); $new_comp1->bar(); //метод выполняющий нужный код + инициирующий событие $new_comp2 = new \common\components\Comp(); $new_comp2->bar(); //метод выполняющий нужный код + инициирующий событие
Например, выполним какой-то код перед выполнением любого метода всех контроллеров приложения:
Event::on(Controller::className(), 'beforeAction', function ($event) { //нужный код, например вызов метода какого-то объекта });
Глобальные события.
Преимущество глобальных событий в том, что им не нужен объект, к событию которого бы присоединялся обработчик и объект, с помощью которого бы это событие инициировалось. Практического применения им я пока не придумал.
Для глобальных событий нужен глобально доступный объект-синглтон, например, экземпляр приложения.
//Устанавливаем обработчик события на пользовательский компонент приложения- класс Comp Yii::$app->on('comp', function ($event) { exit (get_class($event->sender)); // выводит "common\components\Comp" });
//Инициируем событие в нужный момент Yii::$app->trigger('comp', new \yii\base\Event(['sender' => new \common\components\Comp]));
В обработчиках можно получить доступ к объекту, который инициировал событие, с помощью свойства
$event->sender
Данные примеры составлены лично мной, будут вопросы - задавайте в комментариях.