钩子系统原理及ThinkPHP 钩子分析

钩子系统,乍一看,好高大上,让人摸不到头脑。其实,大多技术或者方案,它总要起个名字,要是了解了其原理,这个名字其实也不必纠结。以下都是个人观点:

在这里,可以先看看php中,函数调用的几种方式:

首先,我们来一段php代码:

<?phpfunction deleteData(){echo 'Deleting data! …';}function addData(){echo 'Adding data! …';}if(isset($_GET['act']) && $_GET['act'] == 'delete'){$funcName = 'deleteData';}else{$funcName = 'addData';}$funcName();?>看到这里,会发现,咦,代码还可以这样写?是的,php允许通过变量调用函数。

好吧,再来看一段jQuery代码:

$(function(){$("#clicked_me").click(function(e){console.log("I'm clicked! …");});});上面的代码很容易理解,cliecked_me元素被点击的时候,在控制台输输出:I’m clicked! …

到这里,可以发现:原来有些代码,是可以在某些特定的时间被调用(执行)的,其实,这叫“事件驱动”。

ok,再来一段php代码:

$callback = function(){echo 'Calling back! …<br/>';};function func($cb){echo 'A function named "func" was been calling! …<br/>';$cb();}func($callback);

是的,函数也可以作为另一个函数的参数被传递,然后通过形参这个变量,调用函数。

好吧,你知道的,我又要上代码了:

$funcList = array();// 注册函数$funcList['begin'] = function(){echo 'For loop begins! …<br/>';};$funcList['endNormal'] = function(){echo 'For loop ends successfully! …<br/>';};$funcList['error'] = function(){echo 'An error occured, For loop ends …<br/>';};for($i=0; $i<10; ++$i){if($i == 0 && array_key_exists('begin', $funcList)){handleEvent($funcList['begin']);}if(($rand = rand(0,9)) == 9 && array_key_exists('error', $funcList)){handleEvent($funcList['error']);break;}if($i == 9 && array_key_exists('endNormal', $funcList)){handleEvent($funcList['endNormal']);}}function handleEvent($callback){echo 'An event occured! …<br/>';if(is_callable($callback)) $callback();}好像有点儿意思了:事先注册了几个处理不同“事件”的函数,然后,当“事件”发生时,“触发”那些“事件处理函数”。

好吧,到此有那么一点儿意思了。来看看ThinkPHP 中的 “钩子”源码:

class Hook {//action hooks arrayprivate static $actions = array();/*** ads a function to an action hook* @param $hook* @param $function*/public static function add_action($hook,$function){$hook=mb_strtolower($hook,CHARSET);// create an array of function handlers if it doesn't already existif(!self::exists_action($hook)){self::$actions[$hook] = array();}// append the current function to the list of function handlersif (is_callable($function)){self::$actions[$hook][] = $function;return TRUE;}return FALSE ;}/*** executes the functions for the given hook* @param string $hook* @param array $params* @return boolean true if a hook was setted*/public static function do_action($hook,$params=NULL){$hook=mb_strtolower($hook,CHARSET);if(isset(self::$actions[$hook])){// call each function handler associated with this hookforeach(self::$actions[$hook] as $function){if (is_array($params)){call_user_func_array($function,$params);}else{call_user_func($function);}//cant return anything since we are in a loop! dude!}return TRUE;}return FALSE;}/*** gets the functions for the given hook* @param string $hook* @return mixed*/public static function get_action($hook){$hook=mb_strtolower($hook,CHARSET);return (isset(self::$actions[$hook]))? self::$actions[$hook]:FALSE;}/*** check exists the functions for the given hook* @param string $hook* @return boolean*/public static function exists_action($hook){$hook=mb_strtolower($hook,CHARSET);return (isset(self::$actions[$hook]))? TRUE:FALSE;} }/*** Hooks Shortcuts not in class*/function add_action($hook,$function){return Hook::add_action($hook,$function);}function do_action($hook){return Hook::do_action($hook);}

使用它:

//添加钩子 Hook::add_action('unique_name_hook','some_class::hook_test'); //或使用快捷函数添加钩子:add_action('unique_name_hook','other_class::hello');add_action('unique_name_hook','some_public_function'); //执行钩子do_action('unique_name_hook');//也可以使用 Hook::do_action();来分析下这个 Hook 类:

1:首先,它是个单例类,(只允许有一个类的实例化)。在提供了“注册”和“触发”两个方法。

2:所有“注册”的“事件处理函数”,被保存在对象的成员属性 $actions 中,并且,允许为 “同一个事件”“注册”“多个不同的事件处理函数”。

3:这些“事件处理函数”,可以是某个类的某个成员方法。

其实,看到这里,可以发现,这和 javascript 很像,javascript 允许自定义事件,,也允许为同一事件绑定多个事件处理函数。而且,javascript 还提供了对“事件冒泡”的解决。

总结一下:

1:钩子的实现首先基于:通过变量调用函数。

2:要明白函数作为参数传递,即回调函数,的使用。

3:ThinkPHP 的 Hook 类,涉及到一些 “类的自动加载” 和 “用户自定义函数调用”。

重新开始吧!下次我会吸取教训,不让自己犯同样的错误的;

钩子系统原理及ThinkPHP 钩子分析

相关文章:

你感兴趣的文章:

标签云: