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

行为扩展这个概念是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,返回一个数组,数组格式是 "钩子名"=>array("行为类1","行为类2"......)。
    这里我给一个例子:Application/Common/Conf/tags.php
    <?php
    return array(
        'action_begin'=>array('Home\Behavior\TestBehavior'),
    );
    ?>
    可以看到,我往action_begin这个钩子里面注册了一个行为,其对应的类文件路径是:Application/Behavior/TestBehavior.class.php。注意实际类文件名需要加上Behavior后缀,以及用.class.php作为文件扩展名。
    <?php
    namespace Home\Behavior;
    class TestBehavior{
        function run(){
            echo "这是一个Test行为扩展";
        }
    }
    ?>
    千万要注意第一行的命名空间,对于命名空间不理解的请自行查阅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方法时就会自动触发,有点像猎人的陷阱不是吗?
    <?php
    // 代码省略
        function login(){
            \Think\Hook::listen('login');//监听一个名为login的钩子
        }
    // 代码省略
    ?>
     这里就往login这个钩子里添加了一个test行为,比较懒直接从上面复制过来了,大家理解这个意思就可以。添加多个行为的话可以修改tags.php:
    <?php
    return array(
        'action_begin'=>array('Home\Behavior\TestBehavior', 'Home\Behavior\TongBehavior'),
    );
    ?>
    就是第二个参数变成一个数组,数组里每个元素对应一个行为类,注意,当钩子被触发时,这里面的所有行为都会依次执行。
  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);  //√
    这样我们在行为类里面run方法可以指定一个参数来接收$hello
    function run(&$arg){
        echo $arg;//输出 hello
    }

二、插件篇

看了上面的行为,我们可以总结出一个模式:定义不同的行为,执行同一个方法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方法。这就是行为和插件的区别。

原文:行为扩展以及插件机制介绍

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值