TP5.1钩子的实现以及TP6.0事件的原理

TP框架的钩子功能很早就有了,tp5.1对它的实现又重新构造了,钩子的功能其实就是在代码中侵入其他代码流程。比如在初始化完后监听一个钩子,如果我们注册了这个钩子,并且绑定了一个行为,执行到这里的时候会执行我们绑定的行为。

钩子的使用

创建行为类,不用继承任何类

namespace app\http\behavior;

class ActionBegin
{
    public function run($params)
    {
        echo 'ActionBegin';
    }
}

 配置行为和钩子,在各个模块目录下建一个tag.php文件即可,配置内容只会在对应的模块生效。例如application/tag.php,会对所有模块生效。如果在application/admin/tag.php,则只会对admin模块生效。

// 应用行为扩展定义文件
return [
    // 应用初始化
    'app_init'     => [],
    // 应用开始
    'app_begin'    => [
        'app\http\behavior\LogBegin'
    ],
    // 模块初始化
    'module_init'  => [],
    // 操作开始执行
    'action_begin' => [
        'app\http\behavior\ActionBegin'
    ],
    // 视图内容过滤
    'view_filter'  => [],
    // 日志写入
    'log_write'    => [],
    // 应用结束
    'app_end'      => [],
];

Hook类重要属性

$tags=[],钩子行为定义,不同的钩子对应哪些行为。

static $portal = 'run',表示行为的入口方法。默认是run,所有我们定义行为的时候,要有run方法。

Hook类重要方法

add($tag, $behavior, $first = false),tag是钩子名称,$behavior是行为类名,通过这个方法,把钩子和行为加入到$tags属性中。

listen($tag, $params = null, $once = false),监听钩子,会通过$tag参数去$this->tags属性找对应的行为。如果发现有对应的行为类,就会调用execTag($class, $tag = '', $params = null)去执行这个行为。

TP5.1如何用Hook类实现钩子功能

在模块初始化阶段init(),会把tag.php的配置加入到Hook的属性tags中。

 // 加载行为扩展文件
            if (is_file($path . 'tags.php')) {
                $tags = include $path . 'tags.php';
                if (is_array($tags)) {
                    $this->hook->import($tags);
                }
            }

在不同的阶段监听不同的钩子

// 监听app_init
 $this->hook->listen('app_init');

 tp框架为我们监听了很多个钩子,我们可以直接利用。如果想自定义钩子,可以手动用Hook类的add()注册钩子行为,然后再合适的地方Listen钩子即可。

TP6.0事件的实现

新版的事件系统可以看成是5.1版本行为系统的升级版,事件系统相比行为系统强大的地方在于事件本身可以是一个类,并且可以更好的支持事件订阅者。事件相比较中间件的优势是事件比中间件更加精准定位(或者说粒度更细),并且更适合一些业务场景的扩展。很多原来的钩子都废弃了,因为有些钩子可以直接用中间件来实现。

定义事件

一般我们不用定义事件,框架已经定义好了几个事件

事件 描述 参数
AppInit 应用初始化标签位
HttpRun 应用开始标签位
HttpEnd 应用结束标签位 当前响应对象实例
LogWrite 日志write方法标签位 当前写入的日志信息
RouteLoaded 路由加载完成

 监听事件(一个事件可以有多个监听器)

要监听事件,首先定义好事件监听器

命令php think make:listener AppInit默认会生成一个app\listener\AppInit事件监听类,实现handle方法即可。

在event.php下配置,可以配置多个监听类。只要调用了$event->listen('AppInit'),就会执行监听器的handle方法。

return [   
    'listen'    => [
        'AppInit' => [
            'app\listener\AppInit',
            ]
    ],    
];

 事件订阅(一个监听器可以监听多个事件)

命令php think make:subscribe User默认会生成app\subscribe\User类,或者你可以指定完整类名生成

User类通过on+事件名作为方法,可以对不同的事件进行监听

class User
{
    public function onAppInit()
    {
        echo 'subscribe appinit';
    }
    public function onRouteLoaded()
    {
        echo 'subscribe routeload';
    }

}

在event.php配置事件订阅

 'subscribe' => [
        'app\subscribe\User'
    ],

我们代码中也可以是用Event类来创建事件,然后监听事件,处理事件,这个就是观察者模式编程。当主题对象触发发生变化(触发事件),多个观察者(定义好的监听器)就会执行对应的方法。 一个对象和多个对象的关系的时候用观察者模式。

事件管理类Event.php

重要属性:

$bind:事件别名,['别名'=>'类名'];

$listener:监听者


你可能感兴趣的:(php框架)