1

事件可以将自定义代码“注入”到现有代码中的特定执行点。 附加自定义代码到某个事件,当这个事件被触发时,这些代码就会自动执行。

在处理复杂任务时,事件能很好地起到解耦的作用。事件相对于硬编码的方式来说也增加了服务器资源开销,所以比较建议在任务较为复杂时使用事件!

以下是实例代码,代码中有详细注释:

控制器

<?php

namespace app\controllers;

use app\models\MsgAfterEvent;
use app\models\MsgBeforeEvent;
use app\models\MsgHandler;
use Yii;
use yii\web\Controller;

class EventTestController extends Controller{

    const BEFORE_SEND = 'before_send_msg';
    const AFTER_SEND = 'after_send_msg';

    public function init()
    {
        parent::init(); // TODO: Change the autogenerated stub
        $this->registerEventHandler();
    }

    /**
     * 事件注册
     */
    private function registerEventHandler(){
        //事件处理类
        $msgHandler = new MsgHandler();
        //绑定事件时,可以传入第三个参数。该参数值将会保存到Event类的data属性中
        $this->on(self::BEFORE_SEND,[$msgHandler,'beforeSendMsg'],'who');
        $this->on(self::AFTER_SEND,[$msgHandler,'afterSendMsg']);
    }

    /**
     * 测试用的方法
     */
    public function actionIndex(){
        //发送信息前的事件类
        $msgBefore = new MsgBeforeEvent();
        $msgBefore->date = date('Y-m-d H:i:s',time());
        //触发发送信息前的事件,传入事件类的实例对象,这里的对象充当了保存临时数据的角色
        $this->trigger(self::BEFORE_SEND,$msgBefore);
        //假设这里是个较为复杂的任务
        echo "发送信息...\n";
        //任务执行完毕后,调用发送信息后的事件
        $msgAfter = new MsgAfterEvent();
        $msgAfter->from = 'Jack';
        $msgAfter->to = 'Lucy';
        $msgAfter->message = 'Awesome';
        //触发发送信息后的事件
        $this->trigger(self::AFTER_SEND,$msgAfter);
    }
}

事件处理类

个人觉得可以直接放在models目录下,如果不需要用到数据库操作,可以考虑直接继承Model

<?php
namespace app\models;

use yii\base\Model;

/**
 * 信息发送事件处理类
 * Class MsgHandler
 * @package app\models
 */
class MsgHandler extends Model{

    /**
     * 处理发送信息前的事件
     * @param MsgBeforeEvent $event
     */
    public function beforeSendMsg(MsgBeforeEvent $event){
        //从event中读取日期、和附加信息
        $logContent = "BEFORE:".$event->date.',extraMsg:'.$event->data."\n";
        //写入文件中
        file_put_contents('log.txt',$logContent,FILE_APPEND);
    }

    /**
     * 处理发送信息后的事件
     * @param MsgAfterEvent $event
     */
    public function afterSendMsg(MsgAfterEvent $event){
        /**
         * 从event中读取数据
         */
        $logContent = "AFTER!".$event->from.'发送给'.$event->to.',内容如下:'.$event->message."\n";
        file_put_contents('log.txt',$logContent,FILE_APPEND);
    }
}

消息发送前的事件类

可以放到models目录下

<?php
namespace app\models;

use yii\base\Event;

/**
 * 信息发送前的事件,这里只充当保存数据的角色
 * Class MsgBeforeEvent
 * @package app\models
 */
class MsgBeforeEvent extends Event{
    public $date;
}

消息发送后的事件类

可以放到models目录下

<?php
namespace app\models;

use yii\base\Event;

/**
 * 发送信息后的事件
 * Class MsgAfterEvent
 * @package app\models
 */
class MsgAfterEvent extends Event{
    public $from;
    public $to;
    public $message;
}

处理结果

运行控制器中的index方法后,在log.txt文件中得到如下结果

BEFORE:2017-11-08 14:10:07,extraMsg:who
AFTER!Jack发送给Lucy,内容如下:Awesome

Charles
410 声望25 粉丝

14年入行,后端开发