本文目录导读:

在 PHP 中预留扩展点通常指以下几种场景,我分别给出实现方案:
面向对象设计中的扩展点(最常用)
抽象类 + 模板方法模式
<?php
abstract class PaymentProcessor
{
// 模板方法 - 定义算法骨架
final public function process()
{
$this->validate();
$this->beforePayment();
$result = $this->executePayment();
$this->afterPayment($result);
return $result;
}
// 预留扩展点(必须实现)
abstract protected function executePayment();
// 钩子方法(可选覆盖)
protected function beforePayment() {}
protected function afterPayment($result) {}
protected function validate() {}
}
接口 + 策略模式
<?php
interface SortStrategy
{
public function sort(array $data): array;
}
class QuickSort implements SortStrategy
{
public function sort(array $data): array
{
// 实现
return $data;
}
}
class DataManager
{
private $strategy;
// 通过构造器注入扩展点
public function __construct(SortStrategy $strategy = null)
{
$this->strategy = $strategy ?? new DefaultSort();
}
// 运行时可替换
public function setStrategy(SortStrategy $strategy)
{
$this->strategy = $strategy;
}
}
事件系统/回调机制
<?php
class EventEmitter
{
private $listeners = [];
// 注册事件监听器
public function on($event, callable $callback)
{
$this->listeners[$event][] = $callback;
}
// 触发事件
public function emit($event, ...$args)
{
foreach ($this->listeners[$event] ?? [] as $callback) {
call_user_func_array($callback, $args);
}
}
}
// 使用示例
$emitter = new EventEmitter();
$emitter->on('user.created', function($user) {
// 扩展点:发送欢迎邮件
});
$emitter->emit('user.created', $user);
通过容器和服务提供者(Laravel 风格)
<?php
class Container
{
protected $bindings = [];
protected $instances = [];
// 注册扩展点
public function bind($abstract, $concrete = null)
{
$this->bindings[$abstract] = $concrete;
}
// 解析服务
public function make($abstract)
{
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
$concrete = $this->bindings[$abstract] ?? $abstract;
$instance = new $concrete();
// 允许对象通过宏扩展
$this->instances[$abstract] = $instance;
return $instance;
}
// 宏扩展(运行时添加方法)
public function macro($name, $callback)
{
$this->macros[$name] = $callback;
}
}
配置文件驱动的扩展
<?php
class AppConfig
{
public static function load($configFile)
{
$configs = include $configFile;
foreach ($configs as $key => $value) {
self::$config[$key] = $value;
}
}
// 注册第三方扩展
public static function registerExtension($extension)
{
$extension->boot(self::$config);
}
}
组合使用案例:完整的插件系统
<?php
// 插件接口
interface PluginInterface
{
public function registerListeners(EventManager $events);
public function boot(Container $app);
}
// 插件管理器
class PluginManager
{
private $plugins = [];
private $events;
private $container;
public function __construct(EventManager $events, Container $container)
{
$this->events = $events;
$this->container = $container;
}
// 动态加载插件
public function loadPlugin($pluginClass)
{
if (!is_subclass_of($pluginClass, PluginInterface::class)) {
throw new Exception("Invalid plugin");
}
$plugin = new $pluginClass();
$plugin->registerListeners($this->events);
$plugin->boot($this->container);
$this->plugins[] = $plugin;
}
public function getPlugins()
{
return $this->plugins;
}
}
// 使用示例
$manager = new PluginManager($events, $container);
$manager->loadPlugin(PaymentPlugin::class);
$manager->loadPlugin(LoggingPlugin::class);
PHP 8 特性增强扩展
<?php
// 属性(Attributes)用于标记扩展点
#[Attribute]
class ExtensionPoint
{
public function __construct(public string $purpose = '') {}
}
// 注解驱动扩展
class Service
{
// 标记可扩展方法
#[ExtensionPoint('自定义业务逻辑')]
protected function handleRequest()
{
// 默认实现
}
}
最佳实践建议
- 明确接口:定义清晰的接口,确保扩展点稳定
- 组合优于继承:优先使用策略模式而不是继承
- 配置化:允许通过配置文件开启/关闭扩展
- 依赖注入:使用容器管理扩展的依赖
- 版本兼容:为扩展点制定版本策略
// 最终组合示例
abstract class FrameworkExtension
{
// 必须实现的扩展
abstract public function getName(): string;
// 可选配置
public function configure(array $config): void {}
// 生命周期钩子
public function boot(): void {}
public function shutdown(): void {}
}
选择哪种方式取决于你的具体需求:是简单的回调、灵活的策略、还是完整的插件系统?