1.钩子的使用
行为和钩子是一起使用的,基本原理就是先添加一个钩子,在使用的时候触发这个钩子,触发钩子后去执行的一个行为,其实说白了就是一个方法。理论上使用钩子和自己定义一个全局方法也没啥太大区别。
使用钩子只需要三步:
①.定义一个行为,或者理解为方法
namespace app\index\behavior;
class CheckLang
{
public function run(&$params)
{
// 行为逻辑
}
public function testLog(){
//如果定义名称为test_log则会调用该方法,方法不存在默认会调用run方法
}
}
②. 添加钩子
// 注册 app\index\behavior\CheckLang行为类到app_init标签位
Hook::add('app_init','app\\index\\behavior\\CheckLang');
//会调用CheckLang中的testLog方法
Hook::add('test_log','app\\index\\behavior\\CheckLang');
也可以使用另一种方法进行绑定
如果APP_PATH目录下面和模块目录下面的tags.php都定义了app_init的行为绑定的话,会采用合并模式,如果希望覆盖,那么可以在模块目录下面的tags.php中定义如下:
原理是一样的,无非是自己调用add方法进行添加,或者放到配置里应用启动的时候进行一个读取添加
return [
'app_init'=> [
'app\\index\\behavior\\CheckAuth',
'_overlay'=>true
],
'app_end'=> [
'app\\admin\\behavior\\CronRun'
]
]
③.监听钩子,说白了就是触发钩子,或者调用方法
Hook::listen('action_init');
//也可以传入参数
Hook::listen('action_init',$params);
2.Hook类理解
首先,它是个单例类,(只允许有一个类的实例化)。在提供了“注册”和“触发”两个方法。
文件路径:thinkphp/library/think/Hook.php
namespace think;
class Hook
{
/**
* @var array 标签
*/
private static $tags = [];
public static function add($tag, $behavior, $first = false)
{
//具体逻辑代码
}
public static function listen($tag, &$params = null, $extra = null, $once = false)
{
//具体逻辑代码
}
thinkphp启动的时候会自动加载Hook类,Hook类中有一个静态变量$tags,通过调用add方法会把所有的钩子方法注册到$
tags中,说白了就是一个key-value 数组,key是钩子名称,value是执行的方法也就是行为,这样再需要使用钩子的地方,调用listen方法,就会去$tags变量中寻找对应的该方法,然后再去调用方法
3.thinkphp默认已经添加好的监听
如果自己定义钩子和调用其实和自己在common中定义一个方法差不多,可能就是没有这样清晰,定义钩子的行为一般都是在某个动作完成的前后,比如方法执行前、执行后,订单支付前、支付后。
可以查看thinkphp的App启动类中的run方法
public static function run(Request $request = null)
{
$request = is_null($request) ? Request::instance() : $request;
try {
//省略部分代码
..................
// 监听 app_begin
Hook::listen('app_begin', $dispatch);
// 请求缓存检查
$request->cache(
$config['request_cache'],
$config['request_cache_expire'],
$config['request_cache_except']
);
$data = self::exec($dispatch, $config);
} catch (HttpResponseException $exception) {
$data = $exception->getResponse();
}
//省略部分代码
...............
// 监听 app_end
Hook::listen('app_end', $response);
return $response;
}