首先行为扩展这个概念是TP架构的核心组成之一,关于行为的解释我就粗略的概括一下吧:
TP在从接受到HTTP请求到最终将视图输出,期间经历的很多步骤,这些步骤大家可以在http://document.thinkphp.cn/manual_3_2.html#system_process 这里面看到,这里就不再详细叙述了,那么行为扩展实际上就是在这些流程里埋下了一个钩子,你可以往钩子里添加你自己的业务逻辑,当程序执行到某个钩子位置时将自动触发你的业务逻辑,关于系统预置的一些钩子可以参考:
http://document.thinkphp.cn/manual_3_2.html#behavior_extend

本文的主要目的是教大家如何使用行为扩展和插件,这里为什么要提到"插件"这个词呢?因为在3.2里,有了一个插件的概念,和行为共用一个Hook类,所以放在一起说,原理上并无太大区别。

一、行为扩展篇
1.TP内置行为钩子
我们知道TP中预留了一些行为钩子,比如 action_begin,这个钩子是在动作开始执行时触发,预置的钩子大家通过配置文件注册行为类,大家在Application/Common/Conf目录下创建一个tags.php,这个和3.1是一样的,返回一个数组,数组格式是 "钩子名"=>array("行为类1","行为类2"......)
这里我给一个例子:
Application/Common/Conf/tag.php:
<?php
return array(
"action_begin" => array("Behaviors\\test")
);
?>
可以看到,我往action_begin这个钩子里面注册了一个行为,这个行为就是Behaviors\\test 这里的写法是命名空间写法,其对应的类文件路径是:
Application/Behaviors/testBehavior.class.php
注意实际类文件名需要加上Behavior后缀,以及用.class.php作为文件扩展名。
Application/Behaviors/testBehavior.class.php:
<?php
namespace Behaviors;
class testBehavior{
function run($arg){
echo "这是一个行为扩展".$arg;
}
}
?>
千万要注意第一行的命名空间,对于命名空间不理解的请自行查阅php手册。另外对于TP的自动加载机制,参考手册:
http://document.thinkphp.cn/manual_3_2.html#autoload
行为的执行入口是 run()方法,触发钩子时会自动执行行为类里的run()方法。

2.动态添加钩子和注册行为
通过上面的例子大家才是了解了行为大概是个什么东西,但是对于其执行流程可能还不清楚,这里我来介绍下动态添加钩子和注册行为,使大家对行为执行机制有一个比较清晰的理解。
首先,行为钩子添加和注册行为类,以及触发行为,都是通过Hook类来实现的,Hook类在TP核心包里的ThinkPHP目录下,Hook.class.php.
>>添加钩子以及注册行为:\Think\Hook::add('钩子名','行为')
>>埋设/监听/触发钩子:\Think\Hook::listen('钩子名','传递给run的参数,必须是个变量');
假设我们需要在访问index.php/Public/login.html的时候触发login钩子里的行为,那么首先我们需要在login方法中监听钩子,也就是把钩子埋在login方法里,当访问login方法时就会自动触发,有点像猎人的陷阱不是吗?
function login(){
\Think\Hook::listen('login');//监听一个名为login的钩子
...其他代码略...
}
好了,我们在login方法里监听了login钩子,那么接下来我们往这个钩子里添加一些行为,这样访问login的时候会自动触发这些行为,执行行为类的run方法。
行为在哪里注册呢?
当然得在触发之前注册,1.你可以通过tags.php注册,上面提到过了,只不过把action_begin换成login。2.动态添加,假如你这个钩子只在Public控制器中使用,那么你可以在PublicController的_initialize()初始化方法中动态添加钩子。
function _initialize(){
\Think\Hook::add('login','Behaviors\\test');
}
这里就往login这个钩子里添加了一个test行为,比较懒直接从上面复制过来了,大家理解这个意思就可以。
添加多个行为的话可以这样
\Think\Hook::add('login',array('Behaviors\\test','Behaviors\\test1'...));
就是第二个参数变成一个数组,数组里每个元素对应一个行为类,注意,当钩子被触发时,这里面的所有行为都会依次执行。

3.带参数的行为
上面我们知道了行为是通过run()方法执行的,那么我们想传递一些参数进去怎么办呢?
答案是 \Think\Hook::listen(); 的第二个参数。
注意listen方法定义如下:
static public function listen($tag, &$params=NULL)
可以看到第二个参数是一个引用传递的参数,也就是说,第二个参数必须是一个变量,不能是值,下面的使用方法是错误的:
\Think\Hook::listen('login',"hello"); // x
这样才是正确的
$hello = "hello";
\Think\Hook::listen('login',$hello);//√
关于引用传递的知识这里不作介绍,请自行翻阅PHP手册。

这样我们在行为类里面run方法可以指定一个参数来接收$hello
function run($arg){
echo $arg;//输出 hello
}
当然你也可以
function run(&$arg){
echo $arg;//输出hello
$arg = "bye";
}
这样参数设定为引用类型,你可以在run里面改变原始变量的值。

二、插件
看了上面的行为,我们可以总结出一个模式:
定义不同的行为,执行同一个方法run
而插件呢?
它是可以定义run的,并且相当于在一个行为类里面可以有多个入口,这些入口在不同的条件下触发。
假设我们在tags.php里面添加了这样一个钩子
'showflash' => array('test'),
注意与行为的区别,注册行为需要包含命名空间也就是反斜杠 \\,当没有反斜杠,只有一个单词的时候将认为是一个插件。
插件定义在 Application/Addons/插件名/插件名Addon.class.php
比如上面的test插件就是 Application/Addons/test/testAddon.class.php
插件类的定义:
<?php
namespace Addons\test;
class testAddon{
function showflash(){
echo "这是插件执行入口";
}
}
?>
可以看到一个明显的区别,就是run入口变成了 showflash,和钩子名相同。
有人疑问这样有什么用吗?请继续往下看:

上面我们只定义了一个插件钩子 showflash,假如我们再来一个钩子:

'clearflash'=>array('test');

看到没?这个钩子里面同样注册了一个test插件,而这个test还是上面那个testAddon类,不同的是,你需要为这个clearflash定义一个入口方法,于是testAddon类变成了:
<?php
namespace Addons\test;
class testAddon{
function showflash(){
echo "这是插件执行入口";
}

function clearflash(){
echo "这是另外一个插件钩子入口";
}
}
?>
这样当你不同的钩子注册了同一个插件类时,你需要在插件类里面为这些钩子分别定义入口方法。
而行为类则不是,行为类不管你是不是同一个钩子,它只认准run方法。
这就是行为和插件的区别。

原文地址:http://www.thinkphp.cn/topic/10198.html

ThinkPHP3.2 行为扩展以及插件机制介绍!的更多相关文章

  1. thinkphp 行为扩展以及插件机制介绍

    首先行为扩展这个概念是TP架构的核心组成之一,关于行为的解释我就粗略的概括一下吧:TP在从接受到HTTP请求到最终将视图输出,期间经历的很多步骤,这些步骤大家可以在http://document.th ...

  2. jQuery扩展方法 (插件机制)

    jQuery.extend(object) 扩展jQuery对象本身. 用来在jQuery命名空间上增加新函数. 在jQuery命名空间上增加两个函数: <script> jQuery.e ...

  3. CLI子命令扩展-插件机制实现

    开发CLI工具过程中,为了便于扩展,将CLI的实现分为基础功能和扩展功能.基础功能包括init.build.lint.publish等伴随工程从初始化到最终发布到生产环境,也即为CLI 的core.扩 ...

  4. Maven生命周期和插件机制

    Maven中的一个非常重要的概念是生命周期和插件,这篇文章重点介绍下Maven的生命周期. Maven的生命周期是抽象的,具体的功能是有具体的插件来完成的,Maven有相当多的功能插件,以至于Mave ...

  5. [2017-08-21]Abp系列——如何使用Abp插件机制(注册权限、菜单、路由)

    本系列目录:Abp介绍和经验分享-目录 Abp的模块系统支持插件机制,可以在指定目录中放置模块程序集,然后应用程序启动时会搜索该目录,加载其中所有程序集中的模块. 如何使用这套机制进行功能插件化开发? ...

  6. Dubbo原理和源码解析之“微内核+插件”机制

    github新增仓库 "dubbo-read"(点此查看),集合所有<Dubbo原理和源码解析>系列文章,后续将继续补充该系列,同时将针对Dubbo所做的功能扩展也进行 ...

  7. Cocoapods插件机制浅析

    原文链接 背景 虽然做iOS开发的过程中使用过 Cocoapods, 但是对里面的细节了解其实不算太多,直到这两年做织女项目时,通过对Cocoapods进行Qt支持改造才开始深入了解部分细节,这个过程 ...

  8. 浅谈 Golang 插件机制

    我们知道类似 Java 等半编译半解释型语言编译生成的都是类似中间态的字节码,所以在 Java 里面我们想要实现程序工作的动态扩展,可以通过 Java 的字节码编辑技术([[动态代理#ASM]]/[[ ...

  9. ImitateLogin新增插件机制以及又一个社交网站的支持

    我的文章里已经多次介绍 imitate-login ,这是我最近一直在维护的一个使用c#模拟社交网站登录的开源项目,现在新增了对插件的支持以及一个新的网站(由于某种原因,会在文章结束部分介绍:而且仅会 ...

随机推荐

  1. linux 高级编程之库的使用

    一.静态库与动态库 静态库: .a .lib 动态库: .so .dll 差别(静态库中的代码在链接时就已经复制到可执行文件中,执行时不再依赖库,不会自动使用升级后的库,需要重新产生可执行文件. 动态 ...

  2. ORACLE SELECT INTO NO_DATA_FOUND问题

    存储过程中使用了类似如下语句: SELECT col INTO v_col FROM t_table 当查询不到记录时,会出现“数据未发现”的异常 解决方法: (1)使用MAX函数 SELECT MA ...

  3. win7(X64)系统下cuda7.5和VS2013的配置

    &1 安装 cuda7.5文件:链接:http://pan.baidu.com/s/1bU2zIQ 密码:nvyw &2 环境变量 注意:CUDA_PATH是安装好cuda7.5之后会 ...

  4. java.sql.SQLException: 对只转发结果集的无效操作: last

    出错代码如下:static String u = "user";static String p = "psw";static String url = &quo ...

  5. Android清单文件详解(三)----应用程序的根节点<application>

    <application>节点是AndroidManifest.xml文件中必须持有的一个节点,它包含在<manifest>节点下.通过<application>节 ...

  6. Linux常用指令---$PATH (环境变量)

    实例一:设置临时环境变量 在linux服务器上设置临时环境变量,当退出shell环境时,自动销毁 export JAVA_HOME=/usr/java/jdk1.6.0_32 export class ...

  7. Opencv实现运动检测

    运动检测多种多样,这里的需求只是检测到有运动物体就行了,而且 要尽量减少误报的情况.另外尽量降低CPU的消耗,因为最终需要在树莓派上面运行. 看了一些中文的文章,发现无法很好地理解别人说的内容,反而是 ...

  8. BASE64Decoder 编码(sun.jar)

    Base64 是网络上最常见的用于传输8Bit 字节代码的编码方式之一,大家可以查看RFC2045 -RFC2049 ,上面有MIME 的详细规范.  Base64 要求把每三个8Bit 的字节转换为

  9. php上传图片---初级版

    没有样式,没有淘宝的那种放大截取大小的效果,只是实现了图片上传的功能. 图片超过100k,会出现内部错误服务器错误,需要手动更改配置文件里的MaxRequestLen属性. 下面粘上代码: <? ...

  10. python3 入门 (二) 列表的使用

    列表用于组织其它数值,即写在方括号之间.用逗号分隔开的数值列表.列表内的项目不必全是相同的类型. 列表的定义 student = ['Tom', 'Jack', 'Avril'] 添加元素 将另一个列 ...