CodeIgniter如何设置全局事件监听_CodeIgniter事件驱动编程【编程】
CodeIgniter3无真正全局事件监听,仅提供静态钩子,需显式开启且路径固定,调试困难。CodeIgniter4原生支持发布-订阅事件系统,默认启用,支持自定义事件名和匿名函数。建议不在CI3中强行模拟事件驱动,避免复杂化。
我们先说一个基本判断:CodeIgniter 3 其实没有真正意义上的“全局事件监听”机制,它提供的只是静态钩子(Hook)。而到了 CodeIgniter 4,才原生支持基于发布-订阅的事件系统。把这两者搞混,踩坑的概率几乎是100%。

CI3 里的 hooks.php,本质上只是一组生命周期的插点,跟事件系统是两码事。像 pre_controller、post_system 这些钩子点,是硬编码在框架执行流程中的固定位置,既做不到运行时动态注册,也没法响应任意自定义事件名——Events::trigger() 这种操作在 CI3 里根本不存在的。
具体来说,有几点需要注意:
$config['enable_hooks'] = TRUE必须显式开启,否则整个钩子配置都会静默失效,不会有任何错误提示。- 钩子配置只能写在
application/config/hooks.php,而且必须返回全局变量$hook,路径也相对固定。 - 钩子类里要访问 CI 实例,必须用
get_instance(),不能直接用$this->session之类的写法——因为钩子类本身并不是控制器实例。 - 文件路径(
filepath)是相对于APPPATH的,比如'filepath' => 'hooks'实际对应的是application/hooks/目录。 - 如果钩子文件不存在或不可读,CI3 既不会报错也不会写日志,直接跳过。这大概是调试时最容易让人卡住的地方。
CI4 的 Events.php 才是正儿八经的事件系统
到了 CI4,情况就完全不同了。事件系统默认启用,不需要额外开关,所有监听逻辑都集中在 app/Config/Events.php 里,通过 Events::on() 来绑定回调。
- 监听器支持匿名函数:
Events::on('pre_system', function() { log_message('info', 'App started'); }); - 也支持直接指定类静态方法:
Events::on('post_controller_constructor', [MyAuth::class, 'check']); - 事件名是字符串,可以自定义,比如
'file_updated'。但注意,定义好后需要手动调用Events::trigger('file_updated', $data)才会真正触发。 - 多个监听器按注册顺序依次执行。CI4 原生不提供数字权重参数,如果想控制优先级,只能靠注册的先后顺序来调整。
- 一个容易忽视的坑:监听器内部如果调用了
service('someService'),有可能会引发循环依赖——比如这个服务在初始化时又触发了同一个事件。
在 CI3 里模拟事件驱动?建议别搞太复杂
确实有人尝试用单例类加回调数组的方式,在 CI3 里自己实现一个“事件总线”。但说实话,这个思路在 CI3 里并不太适合:CI3 的生命周期很短,没有自动的依赖注入容器,手动管理监听器的引用很容易造成内存泄漏或者作用域混乱。
如果要给出建议,核心原则是“别造轮子”:
- 尽量避免在钩子中 new 一个全局事件对象并且长期持有,因为 CI3 在请求结束后会销毁所有对象。
- 如果目的只是解耦像“文件更新 → 同步外链表”这种逻辑,用钩子加一个简单的函数调用反而更稳妥:
$this->load->library('file_sync');,然后在钩子里调$this->file_sync->update_links($file_id);就行了。 - 如果真的需要在模块间传递通知,用数据库状态字段加定时任务去拉取,比强行在内存里模拟事件系统更符合 CI3 本身的设计哲学。
最后强调一个容易被忽略的问题:CI3 和 CI4 的事件能力根本就不在同一个抽象层级上。拿着 CI4 的文档去套 CI3 的 hooks.php,或者反过来以为 CI3 的钩子也能响应任意事件名,结果往往是逻辑没执行却死活找不到原因。


































