事件?
CodeIgniter 事件特性提供了一種方法來修改框架的內(nèi)部運(yùn)作流程或功能,而無需修改核心文件的能力。CodeIgniter 遵循著一個(gè)特定的流程來 運(yùn)行。但是,在某些情況下,你可能想在執(zhí)行特定流程時(shí)執(zhí)行某些特定的操作。例如在加載控制器之前或之后立即運(yùn)行一個(gè)特定的腳本?;蛘咴谄渌?某些位置觸發(fā)你的腳本。
事件已發(fā)布/訂閱模式工作,可以在腳本執(zhí)行過程中的某個(gè)時(shí)刻觸發(fā)事件。其他腳本可以通過向 Events 類來注冊(cè)訂閱事件,使它知道在腳本觸發(fā)事件 時(shí)該執(zhí)行什么操作。
啟用事件?
事件始終處于啟用狀態(tài),并且全局可用。
定義事件?
大多數(shù)的事件都定義在 app/Config/Events.php 文件中。不過你也可以通過 Events 類的 on()
方法定義事件。第一個(gè)參數(shù)是事件
名稱,第二個(gè)參數(shù)是當(dāng)觸發(fā)該事件時(shí)執(zhí)行的操作:
use CodeIgniter\Events\Events;
Events::on('pre_system', ['MyClass', 'MyFunction']);
在這個(gè)例子中,任何時(shí)候觸發(fā) pre_controller 事件,都會(huì)創(chuàng)建 MyClass
實(shí)例并運(yùn)行 MyFunction
方法。
第二個(gè)參數(shù)可以是 PHP 能識(shí)別的任何 可調(diào)用結(jié)構(gòu):
// 調(diào)用 some_function 方法
Events::on('pre_system', 'some_function');
// 調(diào)用實(shí)例方法
$user = new User();
Events::on('pre_system', [$user, 'some_method']);
// 調(diào)用靜態(tài)方法
Events::on('pre_system', 'SomeClass::someMethod');
// 使用閉包形式
Events::on('pre_system', function(...$params)
{
. . .
});
設(shè)置執(zhí)行優(yōu)先順序?
由于可以將多個(gè)方法訂閱到一個(gè)事件中,因此需要一種方式來定義這些方法的調(diào)用順序。你可以通過傳遞優(yōu)先級(jí)作為 on()
方法的第三個(gè)參數(shù)來實(shí)現(xiàn)。
事件系統(tǒng)將優(yōu)先執(zhí)行優(yōu)先級(jí)較低的值,優(yōu)先級(jí)最高的值為 1:
Events::on('post_controller_constructor', 'some_function', 25);
如果出現(xiàn)相同優(yōu)先級(jí)的情況,那么事件系統(tǒng)將按定義的順序執(zhí)行。
注解
可以理解為事件系統(tǒng)會(huì)根據(jù)事件名稱分組排序,按第三個(gè)參數(shù)升序排列,然后依次執(zhí)行。
Codeigniter 內(nèi)置了三個(gè)常量供您使用,僅供參考。你也可以不使用它,但你會(huì)發(fā)現(xiàn)他們有助于提高可讀性:
define('EVENT_PRIORITY_LOW', 200);
define('EVENT_PRIORITY_NORMAL', 100);
define('EVENT_PRIORITY_HIGH', 10);
排序后,將按順序執(zhí)行所有訂閱者。如果任意訂閱者返回了布爾類型 false
,訂閱者將停止執(zhí)行。
發(fā)布自定義的事件?
使用事件系統(tǒng),你可以輕松創(chuàng)建自己的事件。要使用此功能,只需要調(diào)用 Events 類的 trigger()
方法即可:
\CodeIgniter\Events\Events::trigger('some_event');
當(dāng)然,你也可以為訂閱者傳遞任意數(shù)量的參數(shù),訂閱者將會(huì)按相同的順序接收參數(shù):
\CodeIgniter\Events\Events::trigger('some_events', $foo, $bar, $baz);
Events::on('some_event', function($foo, $bar, $baz) {
...
});
模擬事件?
在測(cè)試期間,你可能不希望事件被真正的觸發(fā),因?yàn)槊刻彀l(fā)送數(shù)百封電子郵件記緩慢又適得其反。你可以告訴 Events 類使用 simulate()
方法
模擬運(yùn)行事件。如果為 true,那么將跳過所有事件,不過其他的內(nèi)容都會(huì)正常運(yùn)行:
Events::simulate(true);
你也可以傳遞 false 停止模擬:
Events::simulate(false);
事件觸發(fā)點(diǎn)?
以下是 Codeigniter 核心代碼中可用的事件觸發(fā)點(diǎn)列表:
- pre_system 系統(tǒng)執(zhí)行過程中最早被調(diào)用。此時(shí),只有 基準(zhǔn)測(cè)試類 和 鉤子類 被加載了, 還沒有執(zhí)行到路由或其他的流程。
- post_controller_constructor 在你的控制器實(shí)例化之后立即執(zhí)行,控制器的任何方法都還未調(diào)用。
- post_system 最終數(shù)據(jù)發(fā)送到瀏覽器之后,系統(tǒng)執(zhí)行結(jié)束時(shí)調(diào)用。