目前很多框架和系统基本都加入了Hook功能,如:tp,levavel,wordpres等 。因此也在我的PHP框架加入了Hook模块。
百度百科中的解释:
Hook是Windows中提供的一种用以替换DOS下“中断”的系统机制,中文译为“挂钩”或“钩子”。在对特定的系统事件进行hook后,一旦发生已hook事件,对该事件进行hook的程序就会收到系统的通知,这时程序就能在第一时间对该事件做出响应。
虽然这段话说的是windows编程下的,但在PHP中也是类似的。
我的理解是:Hook是一种的插件机制,通过在‘钩子’上挂载一些行为(函数或者类方法,也可以说是插件),最后在需要的地方可以通过这个‘钩子’来执行这些行为。
这种技术很有用,特别是在框架中,框架中预先设计一些钩子放在合适的位置,开发者可以将自己需要的一些功能放置在这些钩子上,当系统运行到钩子放置的位置时,会自动执行这些行为。
没看懂概念的可以看看下面代码,看看输出结果。
<?php
/**
* @description Hook类
* @author luoluolzb
*/
class Hook
{
/**
* 钩子列表
* @var array
*/
protected static $hooks = [];
/**
* 批量导入钩子
* @param array $data
*/
public static function import($data)
{
foreach ($data as $name => $behaviors) {
self::register($name, $behaviors);
}
}
/**
* 在一个钩子下挂载一个或多个行为
* @param string $name 钩子名称
* @param string $plugin 行为类名
*/
public static function register($name, $behaviors)
{
isset(self::$hooks[$name]) || self::$hooks[$name] = [];
if (is_array($behaviors)) {
foreach ($behaviors as $behavior) {
self::_register($name, $behavior);
}
} else {
self::_register($name, $behaviors);
}
}
/**
* 在一个钩子下挂载一个行为
* @param string $name 钩子名称
* @param string $plugin 行为类名
*/
protected static function _register($name, $behavior)
{
if (!class_exists($behavior)) {
throw new RuntimeException("Hook '{$behavior}' Not Found!'");
}
self::$hooks[$name][] = new $behavior;
}
/**
* 触发一个钩子下的行为(按注册顺序执行)
* @param string $name 钩子名称
* @param array $params 传入参数
* @return mixed
*/
public static function trigger($name, $params = [])
{
if (isset(self::$hooks[$name])) {
foreach (self::$hooks[$name] as &$behavior) {
call_user_func_array([$behavior, 'exec'], $params);
}
}
}
}
<?php
require __DIR__ . '/Hook.php';
//以下是三个行为插件
//必须都实现exec函数
//同一个钩子下的插件的exec函数参数定义需保持一致
class SayHello
{
public function exec()
{
echo 'Hello';
echo "\n";
}
}
class SayWorld
{
public function exec()
{
echo 'World';
echo "\n";
}
}
class SayName
{
public function exec($name)
{
echo $name;
echo "\n";
}
}
//挂载单个钩子
Hook::register('say1', 'SayHello');
Hook::register('say2', 'SayWorld');
Hook::register('say3', ['SayWorld', 'SayHello']);
//挂载多个钩子
Hook::register('say4', ['SayName', 'SayName']);
//批量导入多个钩子
Hook::import([
'say2' => ['SayWorld', 'SayHello'],
'say1' => ['SayHello', 'SayWorld'],
]);
//触发钩子
Hook::trigger('say1');
Hook::trigger('say2');
Hook::trigger('say3');
Hook::trigger('say4', ['luoluolzb']);
Hello
Hello
World
World
World
Hello
World
Hello
luoluolzb
luoluolzb
暂无评论,赶紧发表一下你的看法吧。