本文目录导读:

我来详细讲解PHP事件驱动架构的搭建方法,从基础到实践逐步展开。
核心概念
事件驱动架构由三个核心组件组成:
- 事件(Event):系统中发生的事实
- 事件处理器(Handler):响应事件的逻辑
- 事件调度器(Dispatcher):管理事件的发布和订阅
基础实现方案
1 使用现成库(推荐)
Symfony EventDispatcher(最流行):
composer require symfony/event-dispatcher
Laminas EventManager:
composer require laminas/laminas-eventmanager
2 手写轻量级实现
<?php
namespace App\Event;
interface EventInterface
{
public function getName(): string;
}
class OrderCreated implements EventInterface
{
private string $orderId;
public function __construct(string $orderId)
{
$this->orderId = $orderId;
}
public function getName(): string
{
return 'order.created';
}
public function getOrderId(): string
{
return $this->orderId;
}
}
class EventDispatcher
{
private array $listeners = [];
public function addListener(string $eventName, callable $listener, int $priority = 0): void
{
$this->listeners[$eventName][$priority][] = $listener;
// 按优先级排序
ksort($this->listeners[$eventName]);
}
public function dispatch(EventInterface $event): void
{
$eventName = $event->getName();
if (empty($this->listeners[$eventName])) {
return;
}
foreach ($this->listeners[$eventName] as $priority => $listeners) {
foreach ($listeners as $listener) {
call_user_func($listener, $event);
}
}
}
}
完整架构设计
1 目录结构
src/
├── Event/
│ ├── EventInterface.php
│ ├── OrderCreated.php
│ ├── OrderShipped.php
│ └── UserRegistered.php
├── Listener/
│ ├── EmailNotifier.php
│ ├── InventoryUpdater.php
│ └── AnalyticsTracker.php
├── Dispatcher/
│ ├── EventDispatcher.php
│ └── EventSubscriberInterface.php
└── Middleware/
├── LoggingMiddleware.php
└── AuthorizationMiddleware.php
2 高级事件调度器
<?php
namespace App\Dispatcher;
class EventDispatcher
{
private array $listeners = [];
private array $subscribers = [];
private array $middlewares = [];
public function __construct(array $middlewares = [])
{
$this->middlewares = $middlewares;
}
public function addListener(string $eventName, callable $listener, int $priority = 0): self
{
$this->listeners[$eventName][$priority][] = $listener;
ksort($this->listeners[$eventName]);
return $this;
}
public function addSubscriber(EventSubscriberInterface $subscriber): self
{
$this->subscribers[] = $subscriber;
foreach ($subscriber->getSubscribedEvents() as $eventName => $method) {
$priority = 0;
if (is_array($method)) {
[$method, $priority] = $method;
}
$this->addListener($eventName, [$subscriber, $method], $priority);
}
return $this;
}
public function dispatch(string $eventName, array $payload = []): void
{
$event = $this->createEvent($eventName, $payload);
// 应用中间件
$handler = function ($event) {
$this->callListeners($event);
};
foreach (array_reverse($this->middlewares) as $middleware) {
$handler = $middleware($handler);
}
$handler($event);
}
private function createEvent(string $eventName, array $payload): object
{
// 动态创建事件对象
$className = "App\\Event\\" . ucfirst($eventName);
return new $className(...$payload);
}
private function callListeners(object $event): void
{
$eventClass = get_class($event);
$eventName = $this->getEventName($eventClass);
if (empty($this->listeners[$eventName])) {
return;
}
foreach ($this->listeners[$eventName] as $priority => $listeners) {
foreach ($listeners as $listener) {
$result = call_user_func($listener, $event);
if ($result === false) {
break 2; // 停止传播
}
}
}
}
private function getEventName(string $eventClass): string
{
$parts = explode('\\', $eventClass);
return strtolower(end($parts));
}
}
interface EventSubscriberInterface
{
public static function getSubscribedEvents(): array;
}
3 具体事件和监听器
<?php
// 具体的订阅器
class OrderSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
'order.created' => ['onOrderCreated', 10],
'order.shipped' => ['onOrderShipped', 5],
'order.cancelled' => 'onOrderCancelled',
];
}
public function onOrderCreated(OrderCreated $event): void
{
// 发送确认邮件
Mailer::sendOrderConfirmation($event->getOrderId());
// 更新库存
InventoryService::update($event->getOrderId());
// 触发数据分析
Analytics::track('order_created', ['order_id' => $event->getOrderId()]);
}
public function onOrderShipped(OrderShipped $event): void
{
// 更新物流状态
ShippingService::updateStatus($event->getOrderId());
}
public function onOrderCancelled(OrderCancelled $event): void
{
// 退款处理
PaymentService::refund($event->getOrderId());
}
}
集成消息队列
<?php
// EventBus - 支持同步和异步事件
class EventBus
{
private EventDispatcher $dispatcher;
private ?QueueService $queue;
private bool $syncMode = true;
public function __construct(EventDispatcher $dispatcher, ?QueueService $queue = null)
{
$this->dispatcher = $dispatcher;
$this->queue = $queue;
}
public function publish(EventInterface $event): void
{
if ($this->syncMode || !$this->queue) {
// 同步处理
$this->dispatcher->dispatch($event);
} else {
// 异步处理,存入消息队列
$this->queue->push(json_encode([
'event_class' => get_class($event),
'data' => $event->serialize(),
]));
}
}
// 消费队列
public function consume(): void
{
while ($message = $this->queue->pop()) {
$decoded = json_decode($message, true);
$eventClass = $decoded['event_class'];
$event = new $eventClass(...$decoded['data']);
$this->dispatcher->dispatch($event);
}
}
}
异常处理和监控
<?php
namespace App\Middleware;
class ErrorHandlerMiddleware
{
private LoggerInterface $logger;
public function __invoke(callable $next): callable
{
return function ($event) use ($next) {
try {
return $next($event);
} catch (\Throwable $e) {
$this->logger->error('Event processing failed', [
'event' => get_class($event),
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
// TODO: 错误处理策略
throw new EventProcessingException(
'Failed to process event: ' . get_class($event),
0,
$e
);
}
};
}
}
class MetricsMiddleware
{
private StatsCollector $stats;
public function __invoke(callable $next): callable
{
return function ($event) use ($next) {
$startTime = microtime(true);
// 执行后续处理器
$result = $next($event);
// 记录指标
$this->stats->timing(
'event.' . get_class($event),
microtime(true) - $startTime
);
return $result;
};
}
}
最佳实践
1 事件命名规范
- 使用过去时态表示已完成的行为:OrderCreated, UserRegistered
- 使用点分格式:
order.created,payment.completed - 保持一致性:
resource.action
2 匿名函数替代方案
// 使用invokable类
class SendWelcomeEmail
{
public function __invoke(UserRegistered $event): void
{
// 发送欢迎邮件
}
}
// 注册
$dispatcher->addListener('user.registered', new SendWelcomeEmail());
3 配置管理
// config/events.php
return [
'listeners' => [
'order.created' => [
['App\Listeners\SendOrderMail', 'handle'],
['App\Listeners\UpdateInventory', 'handle'],
],
'user.registered' => [
['App\Listeners\SendWelcomeMail', 'handle'],
['App\Listeners\CreateDefaultFiles', 'handle'],
],
],
'subscribers' => [
App\Subscribers\OrderSubscriber::class,
App\Subscribers\UserSubscriber::class,
],
'async_events' => [
'order.created' => true,
'order.shipped' => true,
],
];
测试策略
<?php
class EventDispatcherTest extends TestCase
{
public function testEventDispatch(): void
{
$dispatcher = new EventDispatcher();
$invoked = false;
$dispatcher->addListener('test.event', function () use (&$invoked) {
$invoked = true;
});
$dispatcher->dispatch('test.event');
$this->assertTrue($invoked);
}
public function testListenerPriority(): void
{
$dispatcher = new EventDispatcher();
$executionOrder = [];
$dispatcher->addListener('test.event', function () use (&$executionOrder) {
$executionOrder[] = 'low';
}, 0);
$dispatcher->addListener('test.event', function () use (&$executionOrder) {
$executionOrder[] = 'high';
}, 100);
$dispatcher->dispatch('test.event');
$this->assertEquals(['high', 'low'], $executionOrder);
}
}
性能优化
- 事件缓存:缓存已注册的监听器列表
- 异步处理:将非关键事件放入消息队列
- 事件索引:使用类似事件总线的结构快速定位处理器
- 惰性加载:延迟加载不常用的事件处理器
搭建PHP事件驱动架构的要点:
- 选择合适的实现方案(Symfony/自定义)
- 设计良好的事件命名和结构
- 合理划分同步/异步处理
- 实现完善的错误处理和监控
- 遵循SOLID原则,保持组件解耦
这样的架构能够让你的应用更灵活、可扩展,同时保持代码清晰。