Yii2事件示例解析

Charles發表於2019-02-16

事件可以將自定義程式碼“注入”到現有程式碼中的特定執行點。 附加自定義程式碼到某個事件,當這個事件被觸發時,這些程式碼就會自動執行。

在處理複雜任務時,事件能很好地起到解耦的作用。事件相對於硬編碼的方式來說也增加了伺服器資源開銷,所以比較建議在任務較為複雜時使用事件!

以下是例項程式碼,程式碼中有詳細註釋:

控制器

<?php

namespace appcontrollers;

use appmodelsMsgAfterEvent;
use appmodelsMsgBeforeEvent;
use appmodelsMsgHandler;
use Yii;
use yiiwebController;

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 "傳送資訊...
";
        //任務執行完畢後,呼叫傳送資訊後的事件
        $msgAfter = new MsgAfterEvent();
        $msgAfter->from = `Jack`;
        $msgAfter->to = `Lucy`;
        $msgAfter->message = `Awesome`;
        //觸發傳送資訊後的事件
        $this->trigger(self::AFTER_SEND,$msgAfter);
    }
}

事件處理類

個人覺得可以直接放在models目錄下,如果不需要用到資料庫操作,可以考慮直接繼承Model

<?php
namespace appmodels;

use yiiaseModel;

/**
 * 資訊傳送事件處理類
 * Class MsgHandler
 * @package appmodels
 */
class MsgHandler extends Model{

    /**
     * 處理髮送資訊前的事件
     * @param MsgBeforeEvent $event
     */
    public function beforeSendMsg(MsgBeforeEvent $event){
        //從event中讀取日期、和附加資訊
        $logContent = "BEFORE:".$event->date.`,extraMsg:`.$event->data."
";
        //寫入檔案中
        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."
";
        file_put_contents(`log.txt`,$logContent,FILE_APPEND);
    }
}

訊息傳送前的事件類

可以放到models目錄下

<?php
namespace appmodels;

use yiiaseEvent;

/**
 * 資訊傳送前的事件,這裡只充當儲存資料的角色
 * Class MsgBeforeEvent
 * @package appmodels
 */
class MsgBeforeEvent extends Event{
    public $date;
}

訊息傳送後的事件類

可以放到models目錄下

<?php
namespace appmodels;

use yiiaseEvent;

/**
 * 傳送資訊後的事件
 * Class MsgAfterEvent
 * @package appmodels
 */
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

相關文章