Thinkphp5.1钩子与行为的初步学习
# 什么是钩子和行为
官方手册
行为
【行为定义】:可以把行为想象成在应用执行过程中的一个动 作。例如,在框架的执行流程中,路由检测、静态缓存、用户权限检测是一个行为,大到业务逻辑,小到浏览器检测、多语言检测等都可以当做是一个行为。
【行为作用】:把这些行为抽离出来的目的则是为了无需修改框架和应用,而在外围通过扩展或者配置来改变或者添加一些功能
钩子
【定义】:不同的行为之间也具有着位置共同性,比如,有些行为的作用位置都是在应用执行前,有些行为则是在模板输出之后,我们把这些行为发生作用的位置称之为钩子。
当应用程序运行到这个钩子的时候则会被拦截下来,统一执行绑定到该钩子中的相关行为,这类似于AOP编程中的切面概念,给某个钩子绑定相关行为就成了一种类AOP编程的思想。
特点
一个钩子可以绑定多个行为,执行到某个钩子位置后,会按照绑定的顺序依次执行相关的行为。
在某种特殊情况下,可以设置某个钩子只能执行一次行为,或者是设置在一个钩子的某个行为返回false来强制终止后续的行为执行。
一个行为同样可以被绑定到多个不同钩子。
通俗理解
可以将行为理解为是一个行为类的方法,在框架中行为类、行为方法则是有一定的规则约定;而钩子则是这些行为方法被调用执行的位置点。注意了,要想执行某个钩子中的行为,那行为一定要在应用程序执行到该钩子之前进行绑定。
# Tp5.1 如何设置一个钩子
设置钩子
#1. 引入think\facade\Hook类 use think\facade\Hook; #2. 在需要的位置设置钩子 Hook::listen('钩子名称','参数','是否只有一次有效返回值') - 钩子名称:必须,钩子名称最好由小写字母加下划线'_'组成 - 参数:可选,5.1不支持引用传值,所绑定的行为方法的参数 - 是否只有一次有效返回:可选
Tp5.1系统预留钩子
Tp5.1系统核心预先设计了一些可能会需要的钩子,方便应用的扩展而不必改动框架核心,按照执行顺序如下:
钩子 | 描述 | 参数 |
---|---|---|
app_init | 应用初始化标签位 | 无 |
app_dispatch | 应用调度标签位 | 无 |
app_begin | 应用开始标签位 | 无 |
module_init | 模块初始化标签位 | 无 |
action_begin | 控制器开始标签位 | 当前的callback参数 |
view_filter | 视图输出过滤标签位 | 当前模板渲染输出内容 |
app_end | 应用结束标签位 | 当前响应对象实例 |
log_write | 日志write方法标签位 | 当前写入的日志信息 |
log_write_done | 日志写入完成标签位 | |
response_send | 响应发送标签位 | 当前响应对象 |
response_end | 输出结束标签位 | 当前响应对象实例 |
# 行为定义
行为类、行为方法定义
# 若是该行为类中只有一个行为,只需要定义一个行为入口方法`run`即可 namespace app\index\behavior; class Test { // 当该行为类被绑定到钩子的时候,run行为方法则会在该钩子被触发的时候执行 public function run($params) { // 行为逻辑 } }
若是想要修改行为的入口方法,可以在应用公共文件中修改。
# application\common.php文件进行添加 # 注意,portal函数中的参数自定义,在修改了之后,run方法名就要改为你所定义的了。 use think\Hook; use think\App; $hook = new Hook(new App()); $hook->portal('portal');
注意:如果一个行为类中有多个行为方法,那么在该行为类绑定到钩子的时候,钩子怎么知道要调用执行哪个行为方法呢?
# 上面的问题,Tp5.1对行为方法名进行一定规则约定来解决 # 即钩子在被触发的时候,会调用以钩子名称的驼峰命名(首字母小写)为方法名的行为方法。 namespace app\index\behavior; class Test { // 该行为方法绑定的钩子是**app_init** public function appInit($params){} // 该行为方法绑定的钩子是**app_end** public function appEnd($params){} }
# 行为绑定
在看手册的时候,我觉得行为绑定这里是最容易让人迷糊的,Tp5.1.17钩子绑定行为有两种方式:
- 动态绑定(这个最让新手懵逼)
- 静态绑定
动态绑定
# 动态绑定是通过函数Hook::add()完成的,但新手容易出现的问题是,这个函数要写在哪里, # 其实手册前面已经说过了,行为绑定一定要在钩子被触发之前,也就是要写在你所 # 要绑定的 20000 钩子位置点之前,只不过新手刚接触很容易忽略这点。 # 例子 public function test() { // 行为绑定到钩子,并不需要在同一个函数,只要保证在所绑定的钩子位置点前面就行了 Hook::add('test','app\\test\\behavior\\BehaviorTest'); // 钩子的位置点 Hook::listen('test'); }
静态绑定
在application\tags.php或者application\moduleName\tags.php文件中设置即可。
总结
从上面可以看出对于系统预留的钩子,不建议使用动态绑定,因为你必须清楚知道钩子的位置点,对于自己设置的钩子,两种方式都可以,不过静态绑定个人觉得更加规范,所有的绑定都在统一的配置文件中。
其余的闭包支持、直接执行行为直接看手册即可。传送门
# 例子
下面的例子针对是行为类中只拥有一个行为方法。
# application\test\behavior\BehaviorTest.php <?php namespace app\test\behavior; class BehaviorTest { public function portal($params) { echo $params['name']."钩子执行了方法"."<br>"; } }
# application\common.php <?php // 应用公共文件 use think\Hook; use think\App; $hook = new Hook(new App()); $hook->portal('portal');
# application\test\controller\Index.php <?php namespace app\test\controller; use think\facade\Hook; class Index { public function index() { echo 'start'."<br>"; // 在触发钩子之前,绑定行为到指定钩子 Hook::add('test_1','app\\test\\behavior\\BehaviorTest'); Hook::add('test_2','app\\test\\behavior\\BehaviorTest'); // 调用设置了钩子的函数来触发钩子,进行测试 $this->test_1(); $this->test_2(); } public function test_1() { // 设置钩子test_1 Hook::listen('test_1',['name'=>'test_1']); } public function test_2() { // 设置钩子test_2 Hook::listen('test_2',['name'=>'test_2']); } }阅读更多
- ThinkPHP5 行为和钩子 - 01
- 理解钩子Hook以及在Thinkphp下利用钩子使用行为扩展
- ThinkPHP5 行为和钩子 - 02
- 理解钩子Hook以及在Thinkphp下利用钩子使用行为扩展
- 懂得钩子Hook以及在Thinkphp下利用钩子使用行为扩展
- ThinkPHP5.1入门学习(一) 基础
- HOOK的初步学习(非全局钩子)!
- ThinkPHP5 行为和钩子 - 03
- 懂得钩子Hook以及在Thinkphp下利用钩子使用行为扩展
- thinkPHP5.1学习小结(一)
- 学习ThinkPHP3.2.2(四):增加记录
- web前端学习之bootstrap初步学习
- PostgreSQL的hstore初步学习
- 关于行为树插件Behavior Designer的学习(二)_Composites复合任务
- thinkphp5的入门学习(1)引入数据列表及其操作
- Thinkphp学习心得--命名空间
- 初步学习Flex
- Java学习初步(1)
- ThinkPHP学习(一)开发环境搭建
- 数论初步学习