事件?

CodeIgniter 事件特性提供了一種方法來修改框架的內部運作流程或功能,而無需修改核心文件的能力。CodeIgniter 遵循著一個特定的流程來 運行。但是,在某些情況下,你可能想在執行特定流程時執行某些特定的操作。例如在加載控制器之前或之后立即運行一個特定的腳本。或者在其他的 某些位置觸發你的腳本。

事件已發布/訂閱模式工作,可以在腳本執行過程中的某個時刻觸發事件。其他腳本可以通過向 Events 類來注冊訂閱事件,使它知道在腳本觸發事件 時該執行什么操作。

啟用事件?

事件始終處于啟用狀態,并且全局可用。

定義事件?

大多數的事件都定義在 app/Config/Events.php 文件中。不過你也可以通過 Events 類的 on() 方法定義事件。第一個參數是事件 名稱,第二個參數是當觸發該事件時執行的操作:

use CodeIgniter\Events\Events;

Events::on('pre_system', ['MyClass', 'MyFunction']);

在這個例子中,任何時候觸發 pre_controller 事件,都會創建 MyClass 實例并運行 MyFunction 方法。

第二個參數可以是 PHP 能識別的任何 可調用結構:

// 調用 some_function 方法
Events::on('pre_system', 'some_function');

// 調用實例方法
$user = new User();
Events::on('pre_system', [$user, 'some_method']);

// 調用靜態方法
Events::on('pre_system', 'SomeClass::someMethod');

// 使用閉包形式
Events::on('pre_system', function(...$params)
{
        . . .
});

設置執行優先順序?

由于可以將多個方法訂閱到一個事件中,因此需要一種方式來定義這些方法的調用順序。你可以通過傳遞優先級作為 on() 方法的第三個參數來實現。 事件系統將優先執行優先級較低的值,優先級最高的值為 1:

Events::on('post_controller_constructor', 'some_function', 25);

如果出現相同優先級的情況,那么事件系統將按定義的順序執行。

注解

可以理解為事件系統會根據事件名稱分組排序,按第三個參數升序排列,然后依次執行。

Codeigniter 內置了三個常量供您使用,僅供參考。你也可以不使用它,但你會發現他們有助于提高可讀性:

define('EVENT_PRIORITY_LOW', 200);
define('EVENT_PRIORITY_NORMAL', 100);
define('EVENT_PRIORITY_HIGH', 10);

排序后,將按順序執行所有訂閱者。如果任意訂閱者返回了布爾類型 false,訂閱者將停止執行。

發布自定義的事件?

使用事件系統,你可以輕松創建自己的事件。要使用此功能,只需要調用 Events 類的 trigger() 方法即可:

\CodeIgniter\Events\Events::trigger('some_event');

當然,你也可以為訂閱者傳遞任意數量的參數,訂閱者將會按相同的順序接收參數:

\CodeIgniter\Events\Events::trigger('some_events', $foo, $bar, $baz);

Events::on('some_event', function($foo, $bar, $baz) {
        ...
});

模擬事件?

在測試期間,你可能不希望事件被真正的觸發,因為每天發送數百封電子郵件記緩慢又適得其反。你可以告訴 Events 類使用 simulate() 方法 模擬運行事件。如果為 true,那么將跳過所有事件,不過其他的內容都會正常運行:

Events::simulate(true);

你也可以傳遞 false 停止模擬:

Events::simulate(false);

事件觸發點?

以下是 Codeigniter 核心代碼中可用的事件觸發點列表:

  • pre_system 系統執行過程中最早被調用。此時,只有 基準測試類 和 鉤子類 被加載了, 還沒有執行到路由或其他的流程。
  • post_controller_constructor 在你的控制器實例化之后立即執行,控制器的任何方法都還未調用。
  • post_system 最終數據發送到瀏覽器之后,系統執行結束時調用。