Я прошел через документацию и все статьи о Yii2 events
найденных с помощью Google. Может ли кто-нибудь предоставить мне хороший пример того, как события могут использоваться в Yii2 и где это может показаться логичным?
Я могу объяснить события простым примером. Предположим, вы хотите сделать несколько вещей, когда пользователь сначала регистрируется на сайте, например:
Вы можете попытаться вызвать несколько методов после успешного сохранения пользовательского объекта. Может быть так:
if($model->save()){ $mailObj->sendNewUserMail($model); $notification->setNotification($model); }
Пока это может показаться прекрасным, но что, если количество требований возрастает со временем? Скажем, 10 вещей должны произойти после регистрации пользователем пользователя? События приходят в такие ситуации.
Основы событий
События состоят из следующего цикла.
User
. Подобно const EVENT_NEW_USER='new_user';
, Это используется для добавления обработчиков и для запуска события. $event
. Мы называем этот метод обработчиком. model
используя свой метод, называемый on()
. Вы можете вызывать этот метод много раз, вы хотите – просто вы можете подключить более одного обработчика к одному событию. trigger()
. Обратите внимание, что все упомянутые выше методы являются частью класса Component
. Почти все классы в yii2 унаследованы от этого класса. Да и ActiveRecord
.
Дадим код
Для решения вышеупомянутой проблемы у нас может быть модель User.php
. Я не буду писать весь код здесь.
// in User.php i've declared constant that stores event name const EVENT_NEW_USER = 'new-user'; // say, whenever new user registers, below method will send an email. public function sendMail($event){ echo 'mail sent to admin'; // you code } // one more hanlder. public function notification($event){ echo 'notification created'; }
Здесь следует помнить, что вы не обязаны создавать методы в классе, который создает событие. Вы можете добавить любой статический, не статический метод из любого класса.
Мне нужно приложить над обработчиком события. Основной способ, который я сделал, – использовать метод init()
AR. Итак, вот как:
// this should be inside User.php class. public function init(){ $this->on(self::EVENT_NEW_USER, [$this, 'sendMail']); $this->on(self::EVENT_NEW_USER, [$this, 'notification']); // first parameter is the name of the event and second is the handler. // For handlers I use methods sendMail and notification // from $this class. }
Последняя вещь – вызвать событие. Теперь вам не нужно явно вызывать все необходимые методы, как мы это делали раньше. Вы можете заменить его следующим:
if($model->save()){ $model->trigger(User::EVENT_NEW_USER); }
Все обработчики будут автоматически вызваны.
Для «глобальных» событий.
При желании вы можете создать специализированный класс событий
namespace your\handler\Event\Namespace; class EventUser extends Event { const EVENT_NEW_USER = 'new-user'; }
определить хотя бы один класс обработчика:
namespace your\handler\Event\Namespace; class handlerClass{ // public AND static public static function handleNewUser(EventUser $event) { // $event->user contain the "input" object echo 'mail sent to admin for'. $event->user->username; } }
Внутри компонента компонента config (в данном случае) пользовательский компонент вставляет вам событие:
'components' => [ 'user' => [ ... 'on new-user' => ['your\handler\Event\Namespace\handlerClass', 'handleNewUser'], ], ... ]
Затем в вашем коде вы можете вызвать событие:
Yii::$app->user->trigger(EventUser::EVENT_NEW_USER, new EventUser($user));
ДОБАВИТЬ
Вы также можете использовать закрытие:
пример:
'components' => [ 'user' => [ ... 'on new-user' => function($param){ your\handler\Event\Namespace\handlerClass::handleNewUser($param);}, 'on increment' => function($param){ \Yii::$app->count += $param->value;}, ], ... ]
По умолчанию Yii2 уже предоставляет некоторую декларацию о событиях, вы можете узнать больше об объяснении в BaseActiveRecord .
Вы можете использовать эту переменную так же, как декларировать ее вручную.
public function init() { parent::init(); $this->on(self::EVENT_AFTER_INSERT, [$this, 'exampleMethodHere']); }