亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

目錄 搜索
閱讀前篇 簡介 Yii 是什么 從 Yii 1.1 升級 入門 安裝 Yii 運(yùn)行應(yīng)用 第一次問候 使用Forms 數(shù)據(jù)庫應(yīng)用 使用 Gii 生成代碼 進(jìn)階 應(yīng)用結(jié)構(gòu) 概述 入口腳本 應(yīng)用(Applications) 應(yīng)用組件(Application Components) 控制器(Controllers) 模型(Models) 視圖(views) 模塊(Modules) 過濾器(Filters) 小部件(Widgets) 前端資源(Assets) 擴(kuò)展(Extensions) 請求處理 運(yùn)行概述 啟動引導(dǎo)(Bootstrapping) 路由和創(chuàng)建URL 請求(Requests) 響應(yīng)(Responses) Sessions 和 Cookies 錯誤處理(Handling Errors) 日志(Logging) 關(guān)鍵概念 組件(Component) 屬性(Property) 事件(Events) 行為(Behaviors) 配置(Configurations) 別名(Aliases) 類自動加載(Autoloading) 服務(wù)定位器(Service Locator) 依賴注入容器(Dependency Injection Container) 配合數(shù)據(jù)庫工作 數(shù)據(jù)庫訪問 (Data Access Objects) 查詢生成器(Query Builder) 活動記錄(Active Record) 數(shù)據(jù)庫遷移(Migrations) Sphinx Redis MongoDB Elasticsearch 接收用戶數(shù)據(jù) 創(chuàng)建表單(Creating Forms) 輸入驗(yàn)證(Validating Input) 文件上傳(Uploading Files) 收集列表輸入(Collecting Tabular Input) 多模型的復(fù)合表單(Getting Data for Multiple Models) 顯示數(shù)據(jù) 格式化輸出數(shù)據(jù)(Data Formatting) 分頁(Pagination) 排序(Sorting) 數(shù)據(jù)提供器(Data Providers) 數(shù)據(jù)小部件(Data Widgets) 客戶端腳本使用(Working with Client Scripts) 主題(Theming) 安全 認(rèn)證(Authentication) 授權(quán)(Authorization) 處理密碼(Working with Passwords) 客戶端認(rèn)證(Auth Clients) 最佳安全實(shí)踐(Best Practices) 緩存 概述 數(shù)據(jù)緩存 片段緩存 頁面緩存 HTTP 緩存 RESTfull Web服務(wù) 快速入門(Quick Start) 資源(Resources) 控制器(Controllers) 路由(Routing) 格式化響應(yīng)(Response Formatting) 授權(quán)認(rèn)證(Authentication) 速率限制(Rate Limiting) 版本(Versioning) 錯誤處理(Error Handling) 開發(fā)工具 調(diào)試工具欄和調(diào)試器 使用Gii生成代碼 生成API文檔 測試 概述(Overview) 配置測試環(huán)境(Testing environment setup) 單元測試(Unit Tests) 功能測試(Function Tests) 驗(yàn)收測試(Acceptance Tests) 測試夾具(Fixtures) 高級專題 高級應(yīng)用模板 創(chuàng)建自定義應(yīng)用程序結(jié)構(gòu) 控制臺命令 核心驗(yàn)證器(Core Validators) 國際化 收發(fā)郵件 性能優(yōu)化 共享主機(jī)環(huán)境 模板引擎 集成第三方代碼 小部件 Bootstrap 小部件 Jquery UI 助手類 概述 Array 助手(ArrayHelper) Html 助手(Html) Url 助手(Url)
文字

事件

事件

事件可以將自定義代碼“注入”到現(xiàn)有代碼中的特定執(zhí)行點(diǎn)。附加自定義代碼到某個(gè)事件,當(dāng)這個(gè)事件被觸發(fā)時(shí),這些代碼就會自動執(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í)它就會執(zhí)行??梢允褂靡韵禄卣{(diào)函數(shù)之一:

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

事件處理器的格式是:

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

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

  • yii\base\Event::name:事件名
  • yii\base\Event::sender:調(diào)用?trigger()?方法的對象
  • 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');

// 處理器是對象方法$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è)事件對象,用來傳遞參數(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è)好處。第一,它可以防止拼寫錯誤并支持 IDE 的自動完成。第二,只要簡單檢查常量聲明就能了解一個(gè)類支持哪些事件。

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

// 處理器是對象方法$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ù),除非你在某處存儲了它。以上示例中,假設(shè)匿名函數(shù)存儲為變量$anonymousFunction?。

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

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

類級別的事件處理器

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

例如,活動記錄對象要在每次往數(shù)據(jù)庫新增一條新記錄時(shí)觸發(fā)一個(gè) yii\db\BaseActiveRecord::EVENT_AFTER_INSERT 事件。要追蹤每個(gè)活動記錄對象的新增記錄完成情況,應(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è)事件處理器都會執(zhí)行。在這個(gè)處理器中,可以通過?$event->sender?獲取觸發(fā)事件的對象。

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

可調(diào)用靜態(tài)方法yii\base\Event::trigger()來觸發(fā)一個(gè)類級別事件。類級別事件不與特定對象相關(guān)聯(lián)。因此,它只會引起類級別事件處理器的調(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ā)事件的類名而不是對象實(shí)例。

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

移除類級別的事件處理器只需調(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è)對象要觸發(fā)的事件時(shí),不需要產(chǎn)生該對象。相反,處理器附加和事件觸發(fā)都通過單例(如應(yīng)用實(shí)例)完成。

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