本文目录导读:

- WordPress风格的钩子系统
- 使用事件监听器(Event Listener)
- 中间件模式(Middleware Pattern)
- 使用属性(Attributes)注册(PHP 8+)
- 使用Composer事件(Composer Events)
- 最佳实践
PHP钩子(Hook)是一种设计模式,允许在特定事件发生时执行自定义代码,以下是几种常见的PHP钩子注册方式:
WordPress风格的钩子系统
class HookManager {
private static $filters = [];
private static $actions = [];
// 注册过滤器(修改数据)
public static function addFilter($hook, $callback, $priority = 10, $args = 1) {
self::$filters[$hook][$priority][] = [
'callback' => $callback,
'args' => $args
];
}
// 注册动作(执行操作)
public static function addAction($hook, $callback, $priority = 10, $args = 1) {
self::$actions[$hook][$priority][] = [
'callback' => $callback,
'args' => $args
];
}
// 执行过滤器
public static function applyFilters($hook, $value) {
if (!isset(self::$filters[$hook])) {
return $value;
}
$args = array_slice(func_get_args(), 2);
ksort(self::$filters[$hook]);
foreach (self::$filters[$hook] as $priority => $callbacks) {
foreach ($callbacks as $filter) {
$callback_args = array_merge(array($value), $args);
$value = call_user_func_array($filter['callback'],
array_slice($callback_args, 0, $filter['args']));
}
}
return $value;
}
// 执行动作
public static function doAction($hook, ...$args) {
if (!isset(self::$actions[$hook])) {
return;
}
ksort(self::$actions[$hook]);
foreach (self::$actions[$hook] as $priority => $callbacks) {
foreach ($callbacks as $action) {
call_user_func_array($action['callback'],
array_slice($args, 0, $action['args']));
}
}
}
}
// 注册钩子
HookManager::addFilter('text_content', function($text) {
return strtoupper($text);
}, 10, 1);
HookManager::addAction('user_login', function($username) {
// 记录日志
error_log("用户登录: $username");
}, 10, 1);
// 触发钩子
echo HookManager::applyFilters('text_content', 'hello world');
HookManager::doAction('user_login', 'JohnDoe');
使用事件监听器(Event Listener)
interface EventListenerInterface {
public function handle($event, $data);
}
class EventDispatcher {
private $listeners = [];
// 注册监听器
public function addListener($event, EventListenerInterface $listener, $priority = 0) {
$this->listeners[$event][$priority][] = $listener;
krsort($this->listeners[$event]);
}
// 触发事件
public function dispatch($event, $data = []) {
if (!isset($this->listeners[$event])) {
return;
}
foreach ($this->listeners[$event] as $listeners) {
foreach ($listeners as $listener) {
$listener->handle($event, $data);
}
}
}
}
class UserEventListener implements EventListenerInterface {
public function handle($event, $data) {
switch ($event) {
case 'user.created':
$this->sendWelcomeEmail($data['email']);
break;
case 'user.deleted':
$this->cleanupUserData($data['user_id']);
break;
}
}
}
$dispatcher = new EventDispatcher();
$dispatcher->addListener('user.created', new UserEventListener());
$dispatcher->dispatch('user.created', ['email' => 'test@example.com']);
中间件模式(Middleware Pattern)
class Middleware {
private $handlers = [];
// 注册中间件
public function use(callable $handler) {
$this->handlers[] = $handler;
}
public function handle($request, callable $finalHandler) {
$middleware = array_reverse($this->handlers);
$next = $finalHandler;
// 从最后一个中间件开始包装
foreach ($middleware as $handler) {
$next = function($req) use ($handler, $next) {
return $handler($req, $next);
};
}
return $next($request);
}
}
$app = new Middleware();
$app->use(function($request, $next) {
// 日志中间件
error_log("开始处理请求");
$response = $next($request);
error_log("请求处理完成");
return $response;
});
$app->use(function($request, $next) {
// 认证中间件
if (!$request['authenticated']) {
return "未授权访问";
}
return $next($request);
});
// 最终处理器
$response = $app->handle(['authenticated' => true], function($request) {
return "处理业务逻辑";
});
使用属性(Attributes)注册(PHP 8+)
#[Attribute]
class Hook {
public function __construct(
public string $name,
public int $priority = 10
) {}
}
class HooksCollector {
public static function registerFromClass(string $className) {
$reflection = new ReflectionClass($className);
$methods = $reflection->getMethods();
foreach ($methods as $method) {
$attributes = $method->getAttributes(Hook::class);
foreach ($attributes as $attribute) {
$hook = $attribute->newInstance();
HookManager::addAction(
$hook->name,
[$className, $method->getName()],
$hook->priority
);
}
}
}
}
class UserHooks {
#[Hook('user.created', 5)]
public static function onUserCreated($userId) {
error_log("用户已创建: $userId");
}
#[Hook('user.deleted')]
public static function onUserDeleted($userId) {
// 清理相关数据
}
}
// 自动注册所有钩子
HooksCollector::registerFromClass(UserHooks::class);
使用Composer事件(Composer Events)
利用Composer的autoload机制实现简单的钩子:
// hook.php 文件
return [
'hooks' => [
'before_render' => [
function($content) {
return str_replace(['<script>', '</script>'], '', $content);
},
function($content) {
return nl2br($content);
}
],
'after_save' => [
function($data) {
// 缓存清理
}
]
]
];
// 加载并使用
class HookLoader {
private $hooks;
public function __construct() {
$this->hooks = require 'hooks.php';
}
public function getHooks($name) {
return $this->hooks['hooks'][$name] ?? [];
}
}
最佳实践
- 命名约定:使用清晰的事件名称(如
user.login、order.created) - 优先级处理:支持优先级排序,让高级别优先执行
- 参数传递:明确传递参数数量和类型
- 错误处理:在钩子执行时捕获异常
- 文档记录:记录所有已注册的钩子及其用途
选择哪种方式取决于项目需求,简单项目用函数回调即可,大型框架建议使用完整的事件系统。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播