事件

CodeIgniter 的事件功能提供了一种方法,可以在不修改核心文件的情况下,访问和修改框架的内部工作机制。当 CodeIgniter 运行时,它遵循特定的执行流程。但是,在某些情况下,您可能希望在执行流程的特定阶段执行某些操作。例如,您可能希望在控制器加载之前或之后运行脚本,或者您可能希望在其他位置触发自己的脚本。

事件基于发布/订阅模式,其中事件在脚本执行过程中的某个时间点触发。其他脚本可以通过向 Events 类注册来“订阅”该事件,让它知道它们希望在事件触发时执行操作。

启用事件

事件始终处于启用状态,并且在全局范围内可用。

定义事件

大多数事件在 **app/Config/Events.php** 文件中定义。您可以使用 Events 类的 on() 方法将操作订阅到事件。第一个参数是要订阅的事件的名称。第二个参数是当该事件触发时将运行的可调用对象。

<?php

use CodeIgniter\Events\Events;

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

在此示例中,每当执行 pre_system 事件时,都会创建一个 MyClass 实例,并运行 myFunction() 方法。请注意,第二个参数可以是 PHP 识别的任何形式的 可调用对象

<?php

use CodeIgniter\Events\Events;

// Call a standalone function
Events::on('pre_system', 'some_function');

// Call on an instance method
$user = new \App\Libraries\User();
Events::on('pre_system', [$user, 'someMethod']);

// Call on a static method
Events::on('pre_system', 'SomeClass::someMethod');

// Use a Closure
Events::on('pre_system', static function (...$params) {
    // ...
});

设置优先级

由于多个方法可以订阅单个事件,因此您需要一种方法来定义这些方法的调用顺序。您可以通过将优先级值作为 on() 方法的第三个参数传递来实现。较低的值先执行,值为 1 具有最高优先级,并且较低的值没有限制。

<?php

use CodeIgniter\Events\Events;

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

具有相同优先级的任何订阅者将按照其定义的顺序执行。

从 v4.2.0 开始,定义了三个类常量供您使用,这些常量在值上设置了一些有用的范围。您不需要使用这些常量,但您可能会发现它们有助于可读性。

<?php

use CodeIgniter\Events\Events;

Events::PRIORITY_LOW;    // 200
Events::PRIORITY_NORMAL; // 100
Events::PRIORITY_HIGH;   // 10

重要

常量 EVENT_PRIORITY_LOWEVENT_PRIORITY_NORMALEVENT_PRIORITY_HIGH 已弃用,定义已移至 app/Config/Constants.php。这些常量将在将来的版本中删除。

排序后,所有订阅者将按顺序执行。如果任何订阅者返回布尔值 false,则订阅者的执行将停止。

发布您自己的事件

Events 库让您在自己的代码中轻松创建事件。要使用此功能,您只需在 Events 类上调用 trigger() 方法,并指定事件名称。

<?php

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

您可以通过添加额外的参数将任意数量的参数传递给订阅者。订阅者将按定义的顺序接收参数。

<?php

use CodeIgniter\Events\Events;

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

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

模拟事件

在测试期间,您可能不希望事件实际触发,因为每天发送数百封电子邮件既缓慢又适得其反。您可以使用 simulate() 方法告诉 Events 类仅模拟运行事件。当值为 true 时,所有事件将在触发方法期间被跳过。不过,其他所有内容将照常工作。

<?php

use CodeIgniter\Events\Events;

Events::simulate(true);

您可以通过传递 false 来停止模拟。

<?php

use CodeIgniter\Events\Events;

Events::simulate(false);

事件点

以下是 CodeIgniter 核心代码中可用的事件点列表。

  • pre_system 在系统执行的早期调用。URI、请求和响应已实例化,但页面缓存检查、路由和“之前”控制器过滤器的执行尚未发生。

  • post_controller_constructor 在您的控制器实例化后立即调用,但在任何方法调用发生之前。

  • post_system 在最终渲染的页面发送到浏览器之前调用,在系统执行结束时,在“之后”控制器过滤器执行之后。

  • email 在从 CodeIgniter\Email\Email 成功发送电子邮件后调用。接收一个包含 Email 类属性的数组作为参数。

  • DBQuery 在数据库查询成功或失败后调用。接收 Query 对象。

  • migrate 在成功调用 latest()regress() 后的迁移调用后执行。接收 MigrationRunner 的当前属性以及方法名称。