🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] * * * * * ## 1 监听回调注册源代码(thinkphp/library/think/Hook.php) ~~~ private static $tags = []; ~~~ ~~~ public static function add($tag, $behavior, $first = false) { if (!isset(self::$tags[$tag])) { self::$tags[$tag] = []; } if (is_array($behavior)) { self::$tags[$tag] = array_merge(self::$tags[$tag], $behavior); } elseif ($first) { array_unshift(self::$tags[$tag], $behavior); } else { self::$tags[$tag][] = $behavior; } } ~~~ ~~~ public static function import(array $tags, $recursive = true) { if (!$recursive) { self::$tags = array_merge(self::$tags, $tags); } else { foreach ($tags as $tag => $val) { if (!isset(self::$tags[$tag])) { self::$tags[$tag] = []; } if (!empty($val['_overlay'])) { unset($val['_overlay']); self::$tags[$tag] = $val; } else { self::$tags[$tag] = array_merge(self::$tags[$tag], $val); } } } } ~~~ ~~~ public static function get($tag = '') { if (empty($tag)) { return self::$tags; } else { return self::$tags[$tag]; } } ~~~ ~~~ public static function listen($tag, &$params = null) { if (isset(self::$tags[$tag])) { foreach (self::$tags[$tag] as $name) { if (APP_DEBUG) { Debug::remark('behavior_start', 'time'); } $result = self::exec($name, $tag, $params); if (APP_DEBUG) { Debug::remark('behavior_end', 'time'); Log::record('[ BEHAVIOR ] Run ' . ($name instanceof \Closure ? 'Closure' : $name) . ' @' . $tag . ' [ RunTime:' . Debug::getRangeTime('behavior_start', 'behavior_end') . 's ]', 'info'); } if (false === $result) { return; } } } return; } ~~~ ~~~ public static function exec($class, $tag = '', &$params = null) { if ($class instanceof \Closure) { return $class($params); } $obj = new $class(); return ($tag && is_callable([$obj, $tag])) ? $obj->$tag($params) : $obj->run($params); } ~~~ ## 2 分析 Hook.php是框架的监听回调注册实现文件。也就是事件注册机制的另一种说法。 总的思路是在需要回调的地方插入$tags标签,然后实现相关业务逻辑$behavior。 系统运行过程中,遇到$tags标签,自动运行相关业务逻辑$behavior。 1 静态变量数组$tags 缓存注册的标签行为关联 `private static $tags = [];` 2 add() 注册标签$tags行为$behavior关联.$first可以指定优先级 `public static function add($tag, $behavior, $first = false){}` 3import() 以数组形式注册$tags与$behaviro。$recursive是否覆盖注册 ~~~ public static function import(array $tags, $recursive = true){} ~~~ 4 get() 获取$tags对应行为信息。无参获取全部标签的行为信息 `public static function get($tag = '')` 5 listen() 注册$tag标签的监听。系统运行过程遇到$tag,自动运行关联$begavior `public static function listen($tag, &$params = null)` 6 exec() 以类名方式运行标签$tags对应的行为 `public static function exec($class, $tag = '', &$params = null){}` ~~~ if ($class instanceof \Closure) { return $class($params); } ~~~ 这段代码直接返回对应类的对象。而不是返回$tag标签对应的方法 ## 3 总结 Hook.php 实现了框架的监听注册机制。可以用来在原有业务逻辑中,加入新的业务逻辑,而无需大幅度修改系统结构。使用方法见 [事件与插件注册](http://www.kancloud.cn/zmwtp/tp5/120039)