钩子的使用及原理
CI如同 Laravel、TP 一样提供了 类似 中间件的 功能,支持在控制器执行前及执行后的操作,CI形象的将它比作 钩子 (hooks)。这篇,我们会先写一个使用钩子的例子,然后再去读源码,了解他的使用方式。
- 开启钩子(application/config.php)
/*
|--------------------------------------------------------------------------
| Enable/Disable System Hooks
|--------------------------------------------------------------------------
|
| If you would like to use the 'hooks' feature you must enable it by
| setting this variable to TRUE (boolean). See the user guide for details.
|
*/
$config['enable_hooks'] = TRUE;# FALSE;
- 新建钩子(application\hooks\Test_hook.php)
/**
** 自定义的钩子函数
*/
class Test_hook {
public function say()
{
return 'i am a method say of Test_hook !';
}
}
- 注册钩子
首先,我们在官网可以看到钩子有几种触发时机,我们来了解下
pre_system 在系统执行的早期调用,这个时候只有 基准测试类 和 钩子类 被加载了, 还没有执行到路由或其他的流程。
pre_controller 在你的控制器调用之前执行,所有的基础类都已加载,路由和安全检查也已经完成。
post_controller_constructor 在你的控制器实例化之后立即执行,控制器的任何方法都还尚未调用。
post_controller 在你的控制器完全运行结束时执行。
display_override 覆盖 _display() 方法,该方法用于在系统执行结束时向浏览器发送最终的页面结果。 这可以让你有自己的显示页面的方法。注意你可能需要使用 $this->CI =& get_instance() 方法来获取 CI 超级对象,以及使用 $this->CI->output->get_output() 方法来 获取最终的显示数据。
cache_override 使用你自己的方法来替代 输出类 中的 _display_cache() 方法,这让你有自己的缓存显示机制。
post_system 在最终的页面发送到浏览器之后、在系统的最后期被调用。
我们先使用 pre_controller 挂钩点来注册,将程序先 run 起来
$hook['pre_controller'] = array(
'class' => 'Test_hook',
'function' => 'say',
'filename' => 'Test_hook.php',
'filepath' => 'hooks',
'params' => array()
);
然后,我们在浏览器里访问目标地址,得到
ok,钩子已经成功跑起来了。然后,我们现在去找一下,钩子实现的代码,我们在 CodeIgniter.php 文件 200 Line找到了加载 Hooks 类代码,然后,紧接着,它调用了 Hooks 类的 call_hook 方法,来尝试加载 pre_system 的挂钩点是否存在:
/*
* ------------------------------------------------------
* Instantiate the hooks class
* ------------------------------------------------------
*/
$EXT =& load_class('Hooks', 'core');
/*
* ------------------------------------------------------
* Is there a "pre_system" hook?
* ------------------------------------------------------
*/
$EXT->call_hook('pre_system');
我们进入到 Hook 类中一看究竟,果断先看构造函数:
public function __construct()
{
# 加载配置类
$CFG =& load_class(