距离上次更新本系列已经过去了N久,一段时间下来,从实践中也掌握了不少实用的框架技巧,故而继续更新:
本次主要分享的是CI框架的Hook技巧,即挂载用的钩子;在CI框架中,当我们需要执行一些操作,同时这一操作会对CI 本身的流程影响时,常常有以下两种方式,其一是修改CI 源代码,但这对于后续更新等情况; 会要求重复更改,且易引起BUG,故而不推荐;
其二便是本文所使用的Hook技巧:即通过CI框架在CodeIgniter.php中预置的特定位置来插入特定的代码段,来执行相对应的功能,从而实现不触及CI 代码的前提下,实现自定义功能的操作。
下文为Hook简要的介绍和样例:
1. 概念:
在core文件夹下的Hooks.php中我们可以看到对于Hook的定义:对于__construct()函数,判断了config.php中的enable_hooks值,即当其为TRUE时开启;其次,加载hooks.php中预定义的$hook数组。
$hook['post_controller_constructor'] = array( "class" => "", //钩子类名 "function" => "authenticate",//钩子方法名 "filename" => "authenticate.php",//钩子文件名 "filepath" => "hooks",//钩子路径 "params" => array()//传给钩子的参数,以数组形式传递 );
这里可以看到,我们定义了一个类型为post_controoler_constructor的钩子,其位置在指定的控制器被创建并调用了__constructor()后,指定的函数被调用前;此钩子的含义是authenticate.php中的authenticate函数;
接下来我们可以看下authenticate.php中的文件内容,以更好的解释钩子的作用:
function authenticate(){ if(!isset($_SESSION['user_id'])){ //用户未登陆时 $_SESSION['user_id'] = md5(uniqid(rand(), true)); $_SESSION['user_identity'] = 'visitor'; }else{ //默认的已经登陆用户 } }
这个函数即为对已登陆的用户,略过相关操作;而对未登陆的用户默认设置一个访客ID,这一操作在一些电商等平台上是较为有效的设计(例如购物车等);
而钩子的类型,在CI 中有默认以下几种:[1]
通过这些例子可以很清晰的了解到它们所处的位置,而实际上,这些挂载点也是可以自定义的,在CodeIgniter.php中的call_hook等调用里可以自由的设置(不过要改源代码),我们需要根据自己的实际情况选择合适的挂载点;
下面提供一些例子:
1. 拦截不符合类型的请求:
我们常常需要对某些函数指定类型,即例如indexView()一类的函数,是提供页面加载的,即允许GET类型的访问;而对于indexAction()一类的函数,用于处理POST请求,即限定访问类型为POST,这些操作如果均手动给予限定,则不免显得极为繁琐,而在hook中,在这些请求被实例化控制器对象前即处理,则方便了许多;
这里提供了blocker函数,挂载在cache_override处(controller加载前),对请求的URI进行加工后传递给不同的Method:
function blocker(){ $RTR = & load_class('Router', 'core', isset($routing) ? $routing : NULL); if(is_post()) { $RTR->method .= "Action"; //对类型为POST的请求xx,转发到xxAction方法中 }else if(is_get()){ $RTR->method .= "View"; //对类型为GET的请求xx,转发到xxView方法中 } }
总结:
Hook是一个相当有用的特性,对于有自定义框架需求的童鞋们可以好好研究下并通过这一方式,将CI玩出自己的风格。
[1]CI官方文档:http://codeigniter.org.cn/user_guide/general/hooks.html