如何在yii2中使用事件?

nir*_*del 32 php yii2

我已经阅读了Yii2 events使用Google找到的文档和所有文章.有人能为我提供一个很好的例子,告诉我如何在Yii2中使用事件以及它看起来合乎逻辑吗?

Eja*_*rim 77

我可以用一个简单的例子来解释事件.比方说,当用户首次注册到网站时,您想要做一些事情:

  1. 发送电子邮件给管理员.
  2. 创建通知.
  3. 你说出来的.

成功保存用户对象后,您可以尝试调用几个方法.也许是这样的:

if($model->save()){
   $mailObj->sendNewUserMail($model);
   $notification->setNotification($model);
}
Run Code Online (Sandbox Code Playgroud)

到目前为止看起来似乎还不错,但如果需求数量随着时间的推移而增长呢?假设用户注册后必须发生10件事情?在这种情况下,事件会派上用场.

事件基础

事件由以下周期组成.

  1. 您定义一个事件.说,新用户注册.
  2. 您可以在模型中命名.也许在User模型中添加常数.喜欢const EVENT_NEW_USER='new_user';.这用于添加处理程序和触发事件.
  3. 您定义了一个在事件发生时应该执行某些操作的方法.例如,向管理员发送电子邮件.它必须有一个$event参数.我们将此方法称为处理程序.
  4. 您将该处理程序附加到model使用其调用的方法on().您可以多次调用此方法 - 只需将多个处理程序附加到单个事件即可.
  5. 您可以使用触发事件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';
}
Run Code Online (Sandbox Code Playgroud)

这里要记住的一件事是,您不必在创建事件的类中创建方法.您可以从任何类添加任何静态,非静态方法.

我需要将以上处理程序附加到事件中.我做的基本方法是使用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.
}
Run Code Online (Sandbox Code Playgroud)

最后一件事是触发一个事件.现在您不需要像以前那样显式调用所有必需的方法.您可以通过以下方式替换它:

if($model->save()){
  $model->trigger(User::EVENT_NEW_USER); 
}
Run Code Online (Sandbox Code Playgroud)

将自动调用所有处理程序.

  • 在那里非常好的和彻底的例子,帮助了我很多.我是否也可以像wordpress一样使用这种类型的插件开发?如果是这样,你能说明如上. (2认同)
  • @nirajanpoudel对不起,我不是Wordpress的家伙. (2认同)
  • 另一件重要的事情:将操作放在 `afterSave()` 或 `if($model->save())` 块中将使这些操作在这些块中永远运行。但是如果你使用`Event`,你可以控制它(根据需要打开和关闭)。我的意思是有时您不会运行这些操作,因此您不会附加任何事件。但是当您需要这些操作时,您只需执行`$myModel->on('myEvent', [$myModel, 'myAction1'])`,它们将在“myEvent”发生时运行。根据您的系统需要,您的操作现在是可选的。 (2认同)

Iva*_*oni 23

对于"全球"事件.

您可以选择创建专门的事件类

namespace  your\handler\Event\Namespace;
class EventUser extends Event {
   const EVENT_NEW_USER = 'new-user';
}
Run Code Online (Sandbox Code Playgroud)

定义至少一个处理程序类:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在配置的组件部分(在本例中)用户组件插入事件:

'components' => [
  'user' => [
    ...
    'on new-user' => ['your\handler\Event\Namespace\handlerClass', 'handleNewUser'],
  ],
  ...
]
Run Code Online (Sandbox Code Playgroud)

然后在您的代码中,您可以触发事件:

Yii::$app->user->trigger(EventUser::EVENT_NEW_USER, new EventUser($user));
Run Code Online (Sandbox Code Playgroud)

你也可以使用一个闭包:

  • 允许IDE"检测"函数的使用(用于代码导航)
  • 放一些(小)代码来管理事件

例:

'components' => [
  'user' => [
    ...
    'on new-user' => function($param){ your\handler\Event\Namespace\handlerClass::handleNewUser($param);},
    'on increment' => function($param){ \Yii::$app->count += $param->value;},
  ],   
  ... 
]
Run Code Online (Sandbox Code Playgroud)