入门客AI创业平台(我带你入门,你带我飞行)
博文笔记

ThinkPHP5 行为和钩子 - 01

创建时间:2017-08-04 投稿人: 浏览次数:1635
钩子和行为

ThinkPHP中的行为是一个比较抽象的概念,你可以把行为想象成在应用执行过程中的一个动作。在框架的执行流程中,
例如路由检测是一个行为,静态缓存是一个行为,用户权限检测也是行为,大到业务逻辑,小到浏览器检测、多语言检
测等等都可以当做是一个行为,甚至说你希望给你的网站用户的第一次访问弹出 Hello,world!这些都可以看成是一种行为,
把这些行为抽离出来的目的是为了让你无需改动框架和应用,而在外围通过扩展或者配置来改变或者增加一些功能。

而不同的行为之间也具有位置共同性,比如,有些行为的作用位置都是在应用执行前,有些行为都是在模板输出之后,
我们把这些行为发生作用的位置称之为钩子,当应用程序运行到这个钩子的时候,就会被拦截下来,统一执行相关的行为,
类似于 AOP编程中的“切面”的概念,给某一个钩子绑定相关行为就成了一种类 AOP编程的思想。

一个钩子可以注册多个行为,执行到某个钩子位置后,会按照注册的顺序依次执行相关的行为。但在某些特殊的情况下,
你可以设置某个钩子只能执行一次行为,又或者你可以在一个钩子的某个行为中返回 false来强制终止后续的行为执行;
一个行为可以同时注册到多个不同的钩子上,完全看应用的需求来设计。

钩子的位置是事先设计好的,无论是框架还是应用的,要设置一个钩子,
只需要在相关的位置添加一行代码(事先需要引入 thinkHook类):

    Hook::listen("钩子名称","参数(引用)","额外参数","是否一次有效返回值");

除了钩子名称之外,其它参数都是可选的,注意,如果传入第二个参数的话,因为是引用传值,所以必须传入变量。

系统核心设计提供了一些可能会需要的钩子(位置),尽可能的方便应用的扩展而不必改动框架核心,按照执行顺序依次如下:
钩子            描述                参数
app_init         应用初始化标签位    无
app_begin         应用开始标签位        当前调度信息
module_init     模块初始化标签位    当前请求对象实例
action_begin     控制器开始标签位    当前的callback参数
view_filter     视图输出过滤标签位    当前模板渲染输出内容
app_end         应用结束标签位        当前响应对象实例
response_end     输出结束标签位( V5.0.1+)    当前响应对象实例
log_write         日志write方法标签位    当前写入的日志信息

    其中 log_write钩子仅在调用 Log::write方法的时候执行。

不同的钩子具有不同的行为参数,例如:
// 监听
module_initHook::listen("module_init", $request);

说了半天,行为类到底在哪里呢?应该怎么定义,先别急,我们先要说说怎么才能给钩子绑定行为。

行为定义

对于某个行为本身,通常而言是以一个类的方法或者闭包的方式存在,行为定义有下面几种方式:
<?php
namespace appcommonehavior;
class Hello
{    
    public function run()      
    {        
        echo "hello,world!<br/>";
    }
}

如果是单行为类的话,一般行为类的执行方法是 run方法。如果某个行为类包含了多个行为的话,
那么行为的执行方法是对应钩子的名称,例如:
<?php
namespace appcommonehavior;
class Test
{    
    public function appInit()      
    {        
        echo "app_init test<br/>";
    }
    public function appBegin()      
    {        
        echo "app_begin test";
    }
 }

需要注意一点,在 5.0.4版本以前,行为类的方法应该定义成下面的
(后面的例子我们以 5.0.4版本作为示例)
<?php
namespace appcommonehavior;
class Test
{    
    public function app_init()     
    {        
        echo "app_init test";     
    }    
    public function app_begin()     
    {        
        echo "app_begin test";     
    }
}

5.0.4+版本开始,严格规范了方法名的定义规范采用驼峰法,当然,规则并非强制,
你可以在绑定行为的时候指定执行方法名称。

闭包

我们可以在应用的公共文件中定义一个专门用于 module_init钩子的闭包行为:
$hello = function($request,$module){    echo "hello,".$module."!"; };


这里只是举例说明,一般来说,闭包都是在绑定行为的时候直接定义,无需事先定义。


声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。