我已经阅读了使用谷歌找到的关于Yii2 events
的文档和所有文章。有人能给我一个很好的例子,说明事件如何在Yii2中使用,以及它在哪里看起来合乎逻辑吗?
我可以通过一个简单的例子来解释事件。比方说,当用户第一次注册到网站时,你想做的事情很少,比如:
- 向管理员发送电子邮件
- 创建通知
- 你能说出它的名字
在成功保存用户对象后,您可以尝试调用一些方法。可能是这样的:
if($model->save()){
$mailObj->sendNewUserMail($model);
$notification->setNotification($model);
}
到目前为止,这可能看起来很好,但如果需求数量随着时间的推移而增长呢?假设用户注册后必须发生10件事?在这种情况下,活动很方便。
事件基础
事件由以下循环组成。
- 您定义了一个事件。比如说,新用户注册
- 你可以在你的模型中命名它。可能在
User
模型中添加常数。像const EVENT_NEW_USER='new_user';
。这用于添加处理程序和触发事件 - 您定义了一个方法,该方法应在事件发生时执行某些操作。例如,向管理员发送电子邮件。它必须有一个
$event
参数。我们将此方法称为处理程序 - 您可以使用名为
on()
的方法将该处理程序附加到model
。您可以多次调用此方法,只需将多个处理程序附加到单个事件即可 - 您可以使用
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';
}
这里需要记住的一点是,您不必在创建事件的类中创建方法。您可以从任何类中添加任何静态、非静态方法。
我需要将以上处理程序附加到事件。我做的基本方法是使用AR的init()
方法。以下是如何:
// 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.
parent::init(); // DON'T Forget to call the parent method.
}
最后一件事是触发一个事件。现在,您不需要像以前那样显式调用所有必需的方法。您可以通过以下方式替换它:
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;
}
}
在配置的组件部分内(在本例中),用户组件插入您事件:
'components' => [
'user' => [
...
'on new-user' => ['your'handler'Event'Namespace'handlerClass', 'handleNewUser'],
],
...
]
然后在您的代码中,您可以触发事件:
Yii::$app->user->trigger(EventUser::EVENT_NEW_USER, new EventUser($user));
添加
您也可以使用闭包:
- 允许IDE"检测"函数的使用(用于代码导航)
- 放入一些管理事件的(小)代码
示例:
'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']);
}