thinkphp插件钩子的实现机制是什么
现在主流的cms或者blog等系统中,都内置的有插件系统,但是层层深入、剖析实现的方式,其实都是最简单的钩子的复杂化的实现。
前言插件的执行通过钩子来触发;可以把插件看作挂在钩子上的东西;插件只有在成功实现相应钩子方法并被正确安装启用后才能执行。
开发者也可以用hook('
test'
)方法在控制器只加入钩子,让你的应用具有更好的扩展性;同时也可以模板里加入钩子{:hook('
footer'
)};钩子也支持传入参数hook('
footer'
,array('
test'
=>
1));
向系统暴露你的钩子,就是把你的钩子在相应的文件里列出来,系统会来检测。
{:hooks('documentDetailAfter'
)}
这个的意思就是:相当于在这边 打一个点 ,我们可以将插件挂载到那官方的说法是:文档末尾显示显示的 钩子意思就是说,在文档末尾的时候,会自动调用挂载在那个 钩子 上的插件
举例说明php中所谓的钩子,其实就是一种事件驱动,主要分为&
lsquo;
注册事件&
rsquo;
、&
lsquo;
触发事件&
rsquo;
两步。所谓&
lsquo;
注册事件&
rsquo;
,即目的是给未来可能发生的'
事情'
起一个名字,名字,可以用单例模式或者注册 为一个全局的变量,用的时候直接在对应的方法或者类再或者函数中插入这个变量即可;&
lsquo;
触发事件&
rsquo;
,本质上就是在事件的全局变量中查询要触发的时间名称,然后找到注册号的类与方法,实例化运行。举个例子来说明一下。项目经理给我们了如下的需求:第一天:开发注册的功能。程序员巴拉巴拉,三下五除二就完成了。第二天:在注册前添加发送短信验证码的功能。程序员巴拉巴拉,三峡五除二就又完成了。第三天:注册完成之后,给用户添加相应的积分。程序员又开始巴拉巴拉ing&
hellip;
&
hellip;
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中提供了许多方便的工具和管理后台,使得钩子的使用更加方便和直观。