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

目錄 搜尋
閱讀前篇 簡介 Yii 是什么 從 Yii 1.1 升級 入門 安裝 Yii 運行應用 第一次問候 使用Forms 數(shù)據(jù)庫應用 使用 Gii 生成代碼 進階 應用結構 概述 入口腳本 應用(Applications) 應用組件(Application Components) 控制器(Controllers) 模型(Models) 視圖(views) 模塊(Modules) 過濾器(Filters) 小部件(Widgets) 前端資源(Assets) 擴展(Extensions) 請求處理 運行概述 啟動引導(Bootstrapping) 路由和創(chuàng)建URL 請求(Requests) 響應(Responses) Sessions 和 Cookies 錯誤處理(Handling Errors) 日志(Logging) 關鍵概念 組件(Component) 屬性(Property) 事件(Events) 行為(Behaviors) 配置(Configurations) 別名(Aliases) 類自動加載(Autoloading) 服務定位器(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) 輸入驗證(Validating Input) 文件上傳(Uploading Files) 收集列表輸入(Collecting Tabular Input) 多模型的復合表單(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) 安全 認證(Authentication) 授權(Authorization) 處理密碼(Working with Passwords) 客戶端認證(Auth Clients) 最佳安全實踐(Best Practices) 緩存 概述 數(shù)據(jù)緩存 片段緩存 頁面緩存 HTTP 緩存 RESTfull Web服務 快速入門(Quick Start) 資源(Resources) 控制器(Controllers) 路由(Routing) 格式化響應(Response Formatting) 授權認證(Authentication) 速率限制(Rate Limiting) 版本(Versioning) 錯誤處理(Error Handling) 開發(fā)工具 調試工具欄和調試器 使用Gii生成代碼 生成API文檔 測試 概述(Overview) 配置測試環(huán)境(Testing environment setup) 單元測試(Unit Tests) 功能測試(Function Tests) 驗收測試(Acceptance Tests) 測試夾具(Fixtures) 高級專題 高級應用模板 創(chuàng)建自定義應用程序結構 控制臺命令 核心驗證器(Core Validators) 國際化 收發(fā)郵件 性能優(yōu)化 共享主機環(huán)境 模板引擎 集成第三方代碼 小部件 Bootstrap 小部件 Jquery UI 助手類 概述 Array 助手(ArrayHelper) Html 助手(Html) Url 助手(Url)
文字

事件

事件

事件可以將自定義代碼“注入”到現(xiàn)有代碼中的特定執(zhí)行點。附加自定義代碼到某個事件,當這個事件被觸發(fā)時,這些代碼就會自動執(zhí)行。例如,郵件程序對象成功發(fā)出消息時可觸發(fā)?messageSent?事件。如想追蹤成功發(fā)送的消息,可以附加相應追蹤代碼到?messageSent?事件。

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

事件處理器(Event Handlers)

事件處理器是一個PHP 回調函數(shù),當它所附加到的事件被觸發(fā)時它就會執(zhí)行??梢允褂靡韵禄卣{函數(shù)之一:

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

事件處理器的格式是:

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

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

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

附加事件處理器

調用 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ù)據(jù)作為 yii\base\Component::on() 方法的第三個參數(shù)。數(shù)據(jù)在事件被觸發(fā)和處理器被調用時能被處理器使用。如:

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

事件處理器順序

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

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

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

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

觸發(fā)事件

事件通過調用 yii\base\Component::trigger() 方法觸發(fā),此方法須傳遞事件名,還可以傳遞一個事件對象,用來傳遞參數(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);
    }
}

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

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

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

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);
    }
}

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

移除事件處理器

從事件移除處理器,調用 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);

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

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

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

類級別的事件處理器

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

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

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');
});

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

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

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

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ā)事件的類名而不是對象實例。

注意:因為類級別的處理器響應類和其子類的所有實例觸發(fā)的事件,必須謹慎使用,尤其是底層的基類,如 yii\base\Object。

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

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

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

全局事件

所謂全局事件實際上是一個基于以上敘述的事件機制的戲法。它需要一個全局可訪問的單例,如應用實例。

事件觸發(fā)者不調用其自身的?trigger()?方法,而是調用單例的?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]));

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

然而,因為全局事件的命名空間由各方共享,應合理命名全局事件,如引入一些命名空間(例:"frontend.mail.sent", "backend.mail.sent")。
上一篇: 下一篇: