您的位置:首页 > 编程语言 > PHP开发

ThinkPHP5 行为和钩子 - 02

2017-08-04 10:46 211 查看
绑定行为

要给钩子绑定行为有两种方式:配置绑定和动态绑定。

配置绑定

配置绑定是在应用目录或者模块目录下面的 tags.php文件中配置,app_init和app_begin钩子只

能在应用目录下面的 tags.php文件中配置模块目录下面配置无效,而其它的钩子支持应用和模块配置,

如果同时定义的话,会合并后依次执行行为。

以我们上面定义的两个行为为例,配置方式如下:

return [

'app_init'     =>   ['\app\common\behavior\Hello','\app\common\behavior\Test',],

'app_begin'    =>   ['\app\common\behavior\Test',],    

'module_init'  =>  [function($request){            

        echo 'hello,'.$request->module().'!';          

    },],  

];

假设我们的控制器类如下:

<?php

namespace app\index\controller;

class Index

{    

    public function index()      

    {        

        return 'run index<br/>';

    }  

}

当我们访问URL
http://contoso.org
后,页面输出结果为:

hello,world! app_init testapp_begin testhello,index! run index

配置绑定的行为执行顺序就是配置的定义顺序,我们修改下配置文件里面的定义顺序如下:

return [

'app_init'     =>   ['\app\common\behavior\Test','\app\common\behavior\Hello',],

'app_begin'    =>   ['\app\common\behavior\Test',],

'module_init'  =>   [function($request){

    echo 'hello,'.$request->module().'!';

    },],

];

最终输出的结果变成:

app_init testhello,world! app_begin testhello,index! run index

如果我希望app_init钩子的Test行为执行后不再继续执行后续的行为,可以修改 Test行为类如下:

<?php

namespace app\common\behavior;

class Test

{    

    public function appInit()      

    {        

        echo 'app_init test<br/>';

        return false;

    }    

    public function appBegin()      

    {        

        echo 'app_begin test';        

        return false;      

    }  

}

再次访问的时候,输出结果就变成了

app_init testapp_begin testhello,index! run index

我们看到,app_init钩子绑定的 Hello行为没有被执行。

现在我们在模块的tags.php文件中添加行为绑定

<?php

return [

'module_init'   => [function($request){

        echo 'welcome,'.$request->module().'!';

    },],

];

再次访问后页面输出结果为:

app_init test app_begin test hello,index! welcome,index! run index

可见 modue_init钩子上的应用绑定行为和模块绑定行为同时生效了,

如果希望当前模块的行为覆盖应用绑定的行为,可以使用:

return [

'module_init'    =>  [function($request){

    echo 'welcome,'.$request->module().'!';

},        

'_overlay'    =>  true,],

];

再次访问后,查看页面输出结果变成:

app_init testapp_begin testwelcome,index! run index

module_init钩子只执行了模块的行为。

我们给 Test行为增加一个额外的方法并且也绑定到 module_init钩子

<?php

namespace app\common\behavior;

class Test

{    

    public function appInit()      

    {        

        echo 'app_init test<br/>';

        return false;

    }    

    public function appBegin()      

    {        

        echo 'app_begin test<br/>';

        return false;

    }    

    public function sayHello($request)      

    {        

        echo 'say hello ' . $request->module() . '!';      

    }  

}

V5.0.4+版本开始支持指定方法(包括静态方法执行行为)

因为sayHello方法和钩子名称( module_init对应的方法名应该是 moduleInit)不一致,

所以我们在绑定行为的时候需要改为:

return [

'module_init'    =>  [function($request){

        echo 'welcome,'.$request->module().'!';

    },         

    ['\app\common\behavior\Test','sayHello'],],

];

再次访问页面输出:

app_init test app_begin test hello,index! welcome,index!say hello index! run index

如果sayHello是一个静态方法的话,绑定方式需要从原来的

['\app\common\behavior\Test','sayHello'],

改为:

'\app\common\behavior\Test::sayHello',

动态绑定

配置方式绑定行为理解之后,我们再来看下如何动态绑定某个行为,动态绑定是指使用 Hook::add方法

动态给钩子添加一个行为方法,格式:

    Hook::add('钩子名称','行为定义','是否优先执行');

如果行为需要在应用里面被绑定,就在应用的公共文件 common.php中使用动态绑定代码,如果是模块的绑定行为,

那么也可以在模块的 common.php文件中使用动态绑定。

保持行为类不变的前提下,我们把前面的配置绑定方式改成动态绑定的方式,

首先在 application/common.php中添加如下代码:

use think\Hook;

Hook::add('app_init',['\app\common\behavior\Test','\app\common\behavior\Hello', ]);

Hook::add('app_begin',['\app\common\behavior\Test', ]);

Hook::add('module_init',[function($request){

        echo 'hello,'.$request->module().'!';

    },]

);

在 application/index/common.php中添加如下代码:

use think\Hook;

Hook::add('module_init',[function($request){

            echo 'welcome,'.$request->module().'!';

        },

        ['\app\common\behavior\Test','sayHello'],

    ]

);

然后清空应用和模块的tags.php文件内容,再次访问测试下,输出结果为:

app_init test app_begin test hello,index! welcome,index!say hello index! run index

效果一致。

示例的行为只是做了一个非常简单的输出操作,其实行为可以做很多的事情,

比如检查访问请求、权限检查、请求对象的属性和方法注入、甚至可以进行路由拦截等等,

你唯一需要注意的就是钩子的生效时间点,以及在这个钩子可以做什么有效操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: