thinkphp插件钩子的实现机制是什么

    现在主流的cms或者blog等系统中,都内置的有插件系统,但是层层深入、剖析实现的方式,其实都是最简单的钩子的复杂化的实现。

    前言

    插件的执行通过钩子来触发;可以把插件看作挂在钩子上的东西;插件只有在成功实现相应钩子方法并被正确安装启用后才能执行。

    开发者也可以用hook('
    test'
    )方法在控制器只加入钩子,让你的应用具有更好的扩展性;同时也可以模板里加入钩子{:hook('
    footer'
    )};钩子也支持传入参数hook('
    footer'
    ,array('
    test'
    =>
    1));

    ThinkPHP插件钩子实现机制解密!

    向系统暴露你的钩子,就是把你的钩子在相应的文件里列出来,系统会来检测。

    {:hooks('
    documentDetailAfter'
    )}

    这个的意思就是:相当于在这边 打一个点 ,我们可以将插件挂载到那官方的说法是:文档末尾显示显示的 钩子意思就是说,在文档末尾的时候,会自动调用挂载在那个 钩子 上的插件

    举例说明

    php中所谓的钩子,其实就是一种事件驱动,主要分为&
    lsquo;
    注册事件&
    rsquo;
    、&
    lsquo;
    触发事件&
    rsquo;
    两步。所谓&
    lsquo;
    注册事件&
    rsquo;
    ,即目的是给未来可能发生的'
    事情'
    起一个名字,名字,可以用单例模式或者注册 为一个全局的变量,用的时候直接在对应的方法或者类再或者函数中插入这个变量即可;&
    lsquo;
    触发事件&
    rsquo;
    ,本质上就是在事件的全局变量中查询要触发的时间名称,然后找到注册号的类与方法,实例化运行。举个例子来说明一下。项目经理给我们了如下的需求:第一天:开发注册的功能。程序员巴拉巴拉,三下五除二就完成了。第二天:在注册前添加发送短信验证码的功能。程序员巴拉巴拉,三峡五除二就又完成了。第三天:注册完成之后,给用户添加相应的积分。程序员又开始巴拉巴拉ing&
    hellip;
    &
    hellip;

    class Register{
    public function index(){
    /**
    * 第二天发送短信功能
    */

    /**
    * 第一天注册代码
    */

    /**
    * 第三天增加积分功能
    */
    }
    }

    这样一个人开发还好,多个人开发,势必会造成配合麻烦的问题,同时代码也会变得混乱。作为优秀程序员的我们,当然不容许我们程序中代码冗余、混乱的出现,于是我们把方法写成函数独立出来,方便调用与代码简介。于是形成如下代码:

    class Register{
    public function index(){
    /**
    * 第二天发送短信功能
    */
    sendMsg($data);

    /**
    * 第一天注册代码
    */

    /**
    * 第三天增加积分功能
    */
    sendIntegral($data);

    }
    }
    /**
    * 发送短信
    * @param {[type]} $data [description]
    * @return {[type]} [description]
    */
    function sendMsg($data){
    /*
    balabala
    */
    }
    /**
    * 赠送积分
    * @param {[type]} $data [description]
    * @return {[type]} [description]
    */
    function sendIntegral($data){
    /*
    balabala
    */
    }

    但是我们想要把程序开元出去让更多的人参与,这种直接修改源码码的方式始终不是太好,这个时候,我们就可以使用钩子的方式,在注册成功前后注册两个钩子,我们只需要把钩子告诉开发人员就行了,这样他们不用改变源码码就可以轻易的进行拓展。

    class Register{
    public function index(){

    //注册前钩子
    Hook::run('
    registerBefore'
    );

    /**
    * 注册代码
    */

    //注册后钩子
    Hook::run('
    registerAfter'
    );

    }
    } 钩子的简单实现代码

    目录结构:../hook/Hook.php

    钩子核心类Hook.php: <
    ?php

    namespace hook;

    class Hook{

    static protected $hook = [];


    /**
    * 插件注册
    * @param [type] $name [description]
    * @param [type] $addons [description]
    */
    static public function add($name,$addons){
    self::$hook[$name] = $addons;

    }
    /**
    * 插件执行
    * @param [type] $name [description]
    * @return [type] [description]
    */
    static public function run($name){
    if(isset(self::$hook[$name])){
    $method = (new self::$hook[$name]());

    call_user_func([$method,$name]);

    }

    }
    } 简单的插件demo: <
    ?php
    namespace addons\demo;

    class Demo{
    public function registerBefore(){
    echo '
    registerBefore'
    .'
    <
    /br>
    '
    ;

    }
    public function registerAfter(){
    echo '
    registerAfter'
    .'
    <
    /br>
    '
    ;

    }
    } 插件实现的地方,即上文的注册的文件: <
    ?php
    namespace index\controller;

    use hook\Hook;

    class Index{
    public function index(){
    Hook::run('
    registerBefore'
    );

    echo '
    注册完成'
    .'
    <
    /br>
    '
    ;

    Hook::run('
    registerAfter'
    );


    }
    } 入口文件index.php <
    ?php
    use index\controller\Index;

    spl_autoload_register('
    autoload'
    );

    function autoload($name){
    require_once('
    /'
    .str_replace('
    \\'
    ,'
    /'
    ,$name).'
    .php'
    );

    }
    //插件注册
    hook\Hook::add('
    registerBefore'
    ,'
    \\addons\\demo\\Demo'
    );

    hook\Hook::add('
    registerAfter'
    ,'
    \\addons\\demo\\Demo'
    );

    //调用
    $index = new Index();

    $index->
    index();
    运行接口如下:
    • registerBefore

    • 注册完成

    • registerAfter

    如果要添加新的功能,程序员只要修改demo的插件就可,如果要拓展新的功能,只需要拓展registerBefore和registerAfter即可。




    大家都知道,ThinkPHP是一款非常优秀的PHP开发框架,提供了许多方便开发的功能,其中之一就是插件机制。插件机制作为一种基于事件的扩展方案,提供了非常多的灵活性和扩展性。而在插件机制中,钩子的实现机制是相当重要的一部分,下面就来一起探索一下ThinkPHP中插件钩子的实现机制!
    一、什么是钩子
    钩子是一种通用的扩展机制,顾名思义就是“挂钩”,指的是在核心代码中预留一些可供插件扩展的挂钩点,方便插件实现对核心功能的扩展。钩子其实就是一个事件,当一个事件被触发时,相关的钩子就会被调用,而插件就可以通过对钩子的响应实现对系统的扩展。
    二、ThinkPHP中的插件机制
    ThinkPHP中的插件机制是通过事件驱动的方式实现的。所谓事件驱动,就是先定义好事件,再定义好事件的监听器,当事件触发时,监听器会相应地被调用。下面是ThinkPHP中插件机制的大致实现流程:
    1. 定义事件:在ThinkPHP中,事件通常是通过hook方法定义的。例如,在Controller类中,我们可以用`$this->hook('method')`来定义一个名为“method”的事件。
    2. 注册监听器:当一个事件被定义好后,我们需要将相关的监听器注册到该事件上,通过`$this->registerHook('method', $hook)`实现。其中$hook是一个回调函数,当事件被触发时,该回调函数会被调用。
    3. 激活事件:当事件准备就绪后,我们需要手动调用`$this->trigger('method')`来激活该事件。一旦事件被激活,所有注册在该事件上的监听器都会被调用。
    三、ThinkPHP中的钩子实现机制
    在ThinkPHP中,钩子实现的过程其实就是事件的监听过程。当事件被激活时,所有注册在该事件上的监听器都会被调用,从而实现对核心功能的扩展。下面是ThinkPHP中钩子的实现机制:
    1. 静态调用:ThinkPHP中的钩子是通过静态调用实现的,即`hook::listen('method')`。这样可以避免在每个方法中添加`$this->hook()`的代码。
    2. 自动注册:ThinkPHP中的插件机制支持自动注册,在定义好事件以及监听器后,我们无需手动将监听器注册到事件上,系统会自动完成注册过程。
    3. 管理后台:ThinkPHP中提供了一个钩子管理后台,可以方便地管理系统中已注册的钩子。在后台中,我们可以看到所有已注册的钩子及其对应的监听器,也可以手动添加或删除钩子。
    四、如何实现钩子
    在ThinkPHP中实现钩子非常简单,只需要定义好事件和监听器,然后通过`hook::listen()`方法激活事件即可。下面是一个简单的例子,演示如何实现钩子:
    // 定义一个名为“method”的事件
    $this->hook('method');
    // 注册一个名为“hook1”的监听器
    $this->registerHook('method', 'hook1');
    // 注册一个名为“hook2”的监听器
    $this->registerHook('method', 'hook2');
    // 激活事件
    hook::listen('method');
    在上面的例子中,我们定义了一个名为“method”的事件,并注册了两个监听器“hook1”和“hook2”。当我们调用`hook::listen('method')`时,这两个监听器就会被自动调用,从而实现对系统功能的扩展。
    总结:从本文中我们可以看出,ThinkPHP中的插件机制以及钩子机制非常简单易用,通过使用钩子,我们可以非常方便地对系统的功能进行扩展。同时,ThinkPHP中提供了许多方便的工具和管理后台,使得钩子的使用更加方便和直观。