国产chinesehdxxxx野外,国产av无码专区亚洲av琪琪,播放男人添女人下边视频,成人国产精品一区二区免费看,chinese丰满人妻videos

事件(Events)

2018-02-24 15:40 更新

事件

事件可以將自定義代碼“注入”到現(xiàn)有代碼中的特定執(zhí)行點(diǎn)。附加自定義代碼到某個(gè)事件,當(dāng)這個(gè)事件被觸發(fā)時(shí),這些代碼就會(huì)自動(dòng)執(zhí)行。例如,郵件程序?qū)ο蟪晒Πl(fā)出消息時(shí)可觸發(fā)?messageSent?事件。如想追蹤成功發(fā)送的消息,可以附加相應(yīng)追蹤代碼到messageSent?事件。

Yii 引入了名為 yii\base\Component 的基類以支持事件。如果一個(gè)類需要觸發(fā)事件就應(yīng)該繼承 yii\base\Component 或其子類。

事件處理器(Event Handlers)

事件處理器是一個(gè)PHP 回調(diào)函數(shù),當(dāng)它所附加到的事件被觸發(fā)時(shí)它就會(huì)執(zhí)行。可以使用以下回調(diào)函數(shù)之一:

  • 字符串形式指定的 PHP 全局函數(shù),如?'trim'?;
  • 對(duì)象名和方法名數(shù)組形式指定的對(duì)象方法,如?[$object, $method]?;
  • 類名和方法名數(shù)組形式指定的靜態(tài)類方法,如?[$class, $method]?;
  • 匿名函數(shù),如?function ($event) { ... }?。

事件處理器的格式是:

function ($event) {
    // $event 是 yii\base\Event 或其子類的對(duì)象
}

通過?$event?參數(shù),事件處理器就獲得了以下有關(guān)事件的信息:

  • yii\base\Event::name:事件名
  • yii\base\Event::sender:調(diào)用?trigger()?方法的對(duì)象
  • yii\base\Event::data:附加事件處理器時(shí)傳入的數(shù)據(jù),默認(rèn)為空,后文詳述

附加事件處理器

調(diào)用 yii\base\Component::on() 方法來附加處理器到事件上。如:

$foo = new Foo;

// 處理器是全局函數(shù)
$foo->on(Foo::EVENT_HELLO, 'function_name');

// 處理器是對(duì)象方法
$foo->on(Foo::EVENT_HELLO, [$object, 'methodName']);

// 處理器是靜態(tài)類方法
$foo->on(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']);

// 處理器是匿名函數(shù)
$foo->on(Foo::EVENT_HELLO, function ($event) {
    //事件處理邏輯
});

附加事件處理器時(shí)可以提供額外數(shù)據(jù)作為 yii\base\Component::on() 方法的第三個(gè)參數(shù)。數(shù)據(jù)在事件被觸發(fā)和處理器被調(diào)用時(shí)能被處理器使用。如:

// 當(dāng)事件被觸發(fā)時(shí)以下代碼顯示 "abc"
// 因?yàn)?$event->data 包括被傳遞到 "on" 方法的數(shù)據(jù)
$foo->on(Foo::EVENT_HELLO, function ($event) {
    echo $event->data;
}, 'abc');

事件處理器順序

可以附加一個(gè)或多個(gè)處理器到一個(gè)事件。當(dāng)事件被觸發(fā),已附加的處理器將按附加次序依次調(diào)用。如果某個(gè)處理器需要停止其后的處理器調(diào)用,可以設(shè)置?$event?參數(shù)的 [yii\base\Event::handled]] 屬性為真,如下:

$foo->on(Foo::EVENT_HELLO, function ($event) {
    $event->handled = true;
});

默認(rèn)新附加的事件處理器排在已存在處理器隊(duì)列的最后。因此,這個(gè)處理器將在事件被觸發(fā)時(shí)最后一個(gè)調(diào)用。在處理器隊(duì)列最前面插入新處理器將使該處理器最先調(diào)用,可以傳遞第四個(gè)參數(shù)?$append?為假并調(diào)用 yii\base\Component::on() 方法實(shí)現(xiàn):

$foo->on(Foo::EVENT_HELLO, function ($event) {
    // 這個(gè)處理器將被插入到處理器隊(duì)列的第一位...
}, $data, false);

觸發(fā)事件

事件通過調(diào)用 yii\base\Component::trigger() 方法觸發(fā),此方法須傳遞事件名,還可以傳遞一個(gè)事件對(duì)象,用來傳遞參數(shù)到事件處理器。如:

namespace app\components;

use yii\base\Component;
use yii\base\Event;

class Foo extends Component
{
    const EVENT_HELLO = 'hello';

    public function bar()
    {
        $this->trigger(self::EVENT_HELLO);
    }
}

以上代碼當(dāng)調(diào)用?bar()?,它將觸發(fā)名為?hello?的事件。

提示:推薦使用類常量來表示事件名。上例中,常量?EVENT_HELLO?用來表示?hello?。這有兩個(gè)好處。第一,它可以防止拼寫錯(cuò)誤并支持 IDE 的自動(dòng)完成。第二,只要簡單檢查常量聲明就能了解一個(gè)類支持哪些事件。

有時(shí)想要在觸發(fā)事件時(shí)同時(shí)傳遞一些額外信息到事件處理器。例如,郵件程序要傳遞消息信息到?messageSent?事件的處理器以便處理器了解哪些消息被發(fā)送了。為此,可以提供一個(gè)事件對(duì)象作為 yii\base\Component::trigger() 方法的第二個(gè)參數(shù)。這個(gè)事件對(duì)象必須是 yii\base\Event 類或其子類的實(shí)例。如:

namespace app\components;

use yii\base\Component;
use yii\base\Event;

class MessageEvent extends Event
{
    public $message;
}

class Mailer extends Component
{
    const EVENT_MESSAGE_SENT = 'messageSent';

    public function send($message)
    {
        // ...發(fā)送 $message 的邏輯...

        $event = new MessageEvent;
        $event->message = $message;
        $this->trigger(self::EVENT_MESSAGE_SENT, $event);
    }
}

當(dāng) yii\base\Component::trigger() 方法被調(diào)用時(shí),它將調(diào)用所有附加到命名事件(trigger 方法第一個(gè)參數(shù))的事件處理器。

移除事件處理器

從事件移除處理器,調(diào)用 yii\base\Component::off() 方法。如:

// 處理器是全局函數(shù)
$foo->off(Foo::EVENT_HELLO, 'function_name');

// 處理器是對(duì)象方法
$foo->off(Foo::EVENT_HELLO, [$object, 'methodName']);

// 處理器是靜態(tài)類方法
$foo->off(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']);

// 處理器是匿名函數(shù)
$foo->off(Foo::EVENT_HELLO, $anonymousFunction);

注意當(dāng)匿名函數(shù)附加到事件后一般不要嘗試移除匿名函數(shù),除非你在某處存儲(chǔ)了它。以上示例中,假設(shè)匿名函數(shù)存儲(chǔ)為變量$anonymousFunction?。

移除事件的全部處理器,簡單調(diào)用 yii\base\Component::off() 即可,不需要第二個(gè)參數(shù):

$foo->off(Foo::EVENT_HELLO);

類級(jí)別的事件處理器

以上部分,我們敘述了在實(shí)例級(jí)別如何附加處理器到事件。有時(shí)想要一個(gè)類的所有實(shí)例而不是一個(gè)指定的實(shí)例都響應(yīng)一個(gè)被觸發(fā)的事件,并不是一個(gè)個(gè)附加事件處理器到每個(gè)實(shí)例,而是通過調(diào)用靜態(tài)方法 yii\base\Event::on() 在類級(jí)別附加處理器。

例如,活動(dòng)記錄對(duì)象要在每次往數(shù)據(jù)庫新增一條新記錄時(shí)觸發(fā)一個(gè) yii\db\BaseActiveRecord::EVENT_AFTER_INSERT 事件。要追蹤每個(gè)活動(dòng)記錄對(duì)象的新增記錄完成情況,應(yīng)如下寫代碼:

use Yii;
use yii\base\Event;
use yii\db\ActiveRecord;

Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
    Yii::trace(get_class($event->sender) . ' is inserted');
});

每當(dāng) yii\db\BaseActiveRecord 或其子類的實(shí)例觸發(fā) yii\db\BaseActiveRecord::EVENT_AFTER_INSERT 事件時(shí),這個(gè)事件處理器都會(huì)執(zhí)行。在這個(gè)處理器中,可以通過?$event->sender?獲取觸發(fā)事件的對(duì)象。

當(dāng)對(duì)象觸發(fā)事件時(shí),它首先調(diào)用實(shí)例級(jí)別的處理器,然后才會(huì)調(diào)用類級(jí)別處理器。

可調(diào)用靜態(tài)方法yii\base\Event::trigger()來觸發(fā)一個(gè)類級(jí)別事件。類級(jí)別事件不與特定對(duì)象相關(guān)聯(lián)。因此,它只會(huì)引起類級(jí)別事件處理器的調(diào)用。如:

use yii\base\Event;

Event::on(Foo::className(), Foo::EVENT_HELLO, function ($event) {
    echo $event->sender;  // 顯示 "app\models\Foo"
});

Event::trigger(Foo::className(), Foo::EVENT_HELLO);

注意這種情況下?$event->sender?指向觸發(fā)事件的類名而不是對(duì)象實(shí)例。

注意:因?yàn)轭惣?jí)別的處理器響應(yīng)類和其子類的所有實(shí)例觸發(fā)的事件,必須謹(jǐn)慎使用,尤其是底層的基類,如 yii\base\Object。

移除類級(jí)別的事件處理器只需調(diào)用yii\base\Event::off(),如:

// 移除 $handler
Event::off(Foo::className(), Foo::EVENT_HELLO, $handler);

// 移除 Foo::EVENT_HELLO 事件的全部處理器
Event::off(Foo::className(), Foo::EVENT_HELLO);

全局事件

所謂全局事件實(shí)際上是一個(gè)基于以上敘述的事件機(jī)制的戲法。它需要一個(gè)全局可訪問的單例,如應(yīng)用實(shí)例。

事件觸發(fā)者不調(diào)用其自身的?trigger()?方法,而是調(diào)用單例的?trigger()?方法來觸發(fā)全局事件。類似地,事件處理器被附加到單例的事件。如:

use Yii;
use yii\base\Event;
use app\components\Foo;

Yii::$app->on('bar', function ($event) {
    echo get_class($event->sender);  // 顯示 "app\components\Foo"
});

Yii::$app->trigger('bar', new Event(['sender' => new Foo]));

全局事件的一個(gè)好處是當(dāng)附加處理器到一個(gè)對(duì)象要觸發(fā)的事件時(shí),不需要產(chǎn)生該對(duì)象。相反,處理器附加和事件觸發(fā)都通過單例(如應(yīng)用實(shí)例)完成。

然而,因?yàn)槿质录拿臻g由各方共享,應(yīng)合理命名全局事件,如引入一些命名空間(例:"frontend.mail.sent", "backend.mail.sent")。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)