php 钩子 实现
PHP 钩子实现方法
钩子(Hook)是一种在程序执行过程中插入自定义代码的机制,常用于插件系统或事件驱动开发。PHP中可通过以下方式实现钩子:
使用函数和数组存储钩子
定义钩子数组和添加/执行钩子的函数:
$hooks = [];
function add_hook($hook_name, $callback) {
global $hooks;
$hooks[$hook_name][] = $callback;
}
function do_hook($hook_name, $params = []) {
global $hooks;
if (isset($hooks[$hook_name])) {
foreach ($hooks[$hook_name] as $callback) {
call_user_func_array($callback, $params);
}
}
}
调用示例:
add_hook('before_save', function($data) {
echo "Processing data before save: " . print_r($data, true);
});
$data = ['id' => 1, 'name' => 'Test'];
do_hook('before_save', [$data]);
面向对象实现
创建专门的Hook类管理钩子:
class Hook {
private static $actions = [];
public static function add($hook, $callback, $priority = 10) {
self::$actions[$hook][$priority][] = $callback;
}
public static function run($hook, $args = []) {
if (isset(self::$actions[$hook])) {
ksort(self::$actions[$hook]);
foreach (self::$actions[$hook] as $callbacks) {
foreach ($callbacks as $callback) {
call_user_func_array($callback, $args);
}
}
}
}
}
使用示例:
Hook::add('init', function() {
echo "System initializing...";
});
Hook::run('init');
WordPress风格过滤器实现
实现值过滤的钩子系统:
function apply_filter($hook, $value, ...$args) {
global $filters;
if (isset($filters[$hook])) {
foreach ($filters[$hook] as $callback) {
$value = call_user_func($callback, $value, ...$args);
}
}
return $value;
}
function add_filter($hook, $callback) {
global $filters;
$filters[$hook][] = $callback;
}
使用示例:
add_filter('content', function($text) {
return strtoupper($text);
});
$processed = apply_filter('content', 'hello world');
echo $processed; // 输出: HELLO WORLD
事件驱动实现
使用观察者模式实现更复杂的钩子系统:
class EventDispatcher {
private $listeners = [];
public function addListener($eventName, callable $listener) {
$this->listeners[$eventName][] = $listener;
}
public function dispatch($eventName, $event = null) {
if (isset($this->listeners[$eventName])) {
foreach ($this->listeners[$eventName] as $listener) {
$listener($event);
}
}
}
}
使用示例:

$dispatcher = new EventDispatcher();
$dispatcher->addListener('user.login', function($user) {
echo "User {$user} logged in";
});
$dispatcher->dispatch('user.login', 'admin');
实现要点
- 钩子名称应具有唯一性和描述性
- 考虑添加优先级参数控制执行顺序
- 可以添加移除钩子的功能
- 对于生产环境建议添加类型检查和错误处理
- 考虑性能影响,避免过多钩子调用
以上方法可根据实际需求组合使用,构建灵活的插件架构或事件处理系统。






