
PHP钩子系统与插件架构设计钩子系统和插件架构让应用的功能可以动态扩展。插件可以在不修改核心代码的情况下添加新功能。今天说说PHP中插件系统的实现。插件系统的核心是注册点机制。核心程序在特定位置触发钩子插件可以注册到这些钩子上。phpclass HookManager{private static array $hooks [];public static function addFilter(string $name, callable $callback, int $priority 10): void{self::$hooks[filter][$name][] [callback $callback, priority $priority];usort(self::$hooks[filter][$name], fn($a, $b) $a[priority] - $b[priority]);}public static function addAction(string $name, callable $callback, int $priority 10): void{self::$hooks[action][$name][] [callback $callback, priority $priority];usort(self::$hooks[action][$name], fn($a, $b) $a[priority] - $b[priority]);}public static function applyFilter(string $name, mixed $value, ...$args): mixed{if (!isset(self::$hooks[filter][$name])) return $value;foreach (self::$hooks[filter][$name] as $hook) {$value ($hook[callback])($value, ...$args);}return $value;}public static function doAction(string $name, ...$args): void{if (!isset(self::$hooks[action][$name])) return;foreach (self::$hooks[action][$name] as $hook) {($hook[callback])(...$args);}}public static function removeAll(string $name, string $type null): void{if ($type) {unset(self::$hooks[$type][$name]);} else {unset(self::$hooks[filter][$name], self::$hooks[action][$name]);}}public static function getHooks(): array{return self::$hooks;}}// 核心内容处理class ContentProcessor{public function process(string $content): string{HookManager::doAction(before_process_content, $content);// 核心处理$content $this-sanitize($content);// 应用过滤器$content HookManager::applyFilter(content, $content);HookManager::doAction(after_process_content, $content);return $content;}private function sanitize(string $content): string{return strip_tags($content);}}// 插件1字数统计class WordCountPlugin{public static function init(): void{HookManager::addAction(after_process_content, [self::class, countWords]);}public static function countWords(string $content): void{$count str_word_count($content, 0, 中文);echo \n;}}// 插件2敏感词过滤class SensitiveWordPlugin{private static array $words [敏感词1, 敏感词2, 不良信息];public static function init(): void{HookManager::addFilter(content, [self::class, filterWords], 5);}public static function filterWords(string $content): string{foreach (self::$words as $word) {$content str_replace($word, str_repeat(*, mb_strlen($word)), $content);}return $content;}}// 插件3自动添加版权class CopyrightPlugin{public static function init(): void{HookManager::addFilter(content, [self::class, addCopyright], 20);}public static function addCopyright(string $content): string{return $content . \n\n版权归原作者所有;}}// 注册插件WordCountPlugin::init();SensitiveWordPlugin::init();CopyrightPlugin::init();$processor new ContentProcessor();$result $processor-process(这是一段包含敏感词1的内容需要处理。);echo $result;?插件管理器负责加载和管理插件。phpclass PluginManager{private array $plugins [];private string $pluginDir;public function __construct(string $pluginDir __DIR__ . /plugins){$this-pluginDir rtrim($pluginDir, /);}public function scanPlugins(): array{$plugins [];$dirs glob($this-pluginDir . /*, GLOB_ONLYDIR);foreach ($dirs as $dir) {$manifest $dir . /plugin.json;if (file_exists($manifest)) {$config json_decode(file_get_contents($manifest), true);if ($config isset($config[name])) {$plugins[] $config;}}}return $plugins;}public function loadPlugin(string $name): bool{$pluginFile $this-pluginDir . /{$name}/{$name}.php;if (!file_exists($pluginFile)) {throw new RuntimeException(插件文件不存在: {$name});}require_once $pluginFile;$className \\Plugin\\{$name}\\{$name}Plugin;if (!class_exists($className)) {throw new RuntimeException(插件类不存在: {$className});}$plugin new $className();$plugin-register();$this-plugins[$name] $plugin;return true;}public function loadAllPlugins(): void{$plugins $this-scanPlugins();foreach ($plugins as $plugin) {try {$this-loadPlugin($plugin[name]);} catch (Exception $e) {error_log(插件加载失败: {$plugin[name]} - {$e-getMessage()});}}}public function unloadPlugin(string $name): void{if (isset($this-plugins[$name])) {$this-plugins[$name]-unregister();unset($this-plugins[$name]);}}}?// plugins/analytics/plugin.json// {// name: analytics,// version: 1.0.0,// description: 统计插件,// author: 张三,// hooks: [page_view, click_event]// }?// plugins/analytics/analytics.phpnamespace Plugin\Analytics;class AnalyticsPlugin{public function register(): void{HookManager::addAction(page_view, [$this, trackPageView], 5);HookManager::addAction(click_event, [$this, trackClick], 5);}public function unregister(): void{HookManager::removeAll(page_view, action);HookManager::removeAll(click_event, action);}public function trackPageView(string $url): void{$log date(Y-m-d H:i:s) . VIEW: {$url}\n;file_put_contents(/tmp/analytics.log, $log, FILE_APPEND);}public function trackClick(string $element, string $url): void{$log date(Y-m-d H:i:s) . CLICK: {$element} {$url}\n;file_put_contents(/tmp/analytics.log, $log, FILE_APPEND);}}?钩子系统和插件架构让应用的核心功能和扩展功能分离。核心程序提供扩展点插件通过钩子介入。这种架构让第三方开发者可以为应用开发插件丰富了应用的生态。WordPress的成功很大程度上归功于它的钩子系统。