本文目录导读:

我将详细解释PHP事件调度器的原理,从基础概念到实际实现。
核心概念
事件调度器的三个核心组件:
- 事件(Event):发生的动作或状态变化
- 监听器(Listener):对事件做出响应的回调函数
- 调度器(Dispatcher):维护事件和监听器的映射关系,并触发事件
基础实现原理
简单的观察者模式实现:
<?php
interface EventInterface
{
public function getName(): string;
}
class OrderCreatedEvent implements EventInterface
{
public function getName(): string
{
return 'order.created';
}
public function getOrder()
{
return $this->order;
}
}
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 (!isset($this->listeners[$eventName])) {
return;
}
// 按优先级顺序执行监听器
foreach ($this->listeners[$eventName] as $priority => $listeners) {
foreach ($listeners as $listener) {
// 调用回调函数
call_user_func($listener, $event);
}
}
}
// 移除监听器
public function removeListener(string $eventName, callable $listener): void
{
// 实现逻辑
}
}
// 使用示例
$dispatcher = new EventDispatcher();
$dispatcher->addListener('order.created', function(OrderCreatedEvent $event) {
$order = $event->getOrder();
// 发送邮件通知
echo "已发送订单通知邮件\n";
});
$dispatcher->addListener('order.created', function(OrderCreatedEvent $event) {
// 更新库存
echo "已更新库存\n";
}, 10); // 优先级更高
$dispatcher->dispatch(new OrderCreatedEvent($order));
?>
高级特性实现
1 事件传播控制
<?php
class EventDispatcher
{
private array $listeners = [];
public function dispatch(EventInterface $event): EventInterface
{
$eventName = $event->getName();
if (isset($this->listeners[$eventName])) {
foreach ($this->listeners[$eventName] as $listener) {
// 检测事件是否被停止传播
if ($event->isPropagationStopped()) {
break;
}
$listener($event);
}
}
return $event;
}
}
// 支持停止传播的事件
interface StoppableEventInterface extends EventInterface
{
public function stopPropagation(): void;
public function isPropagationStopped(): bool;
}
class OrderCreatedEvent implements StoppableEventInterface
{
private bool $propagationStopped = false;
public function stopPropagation(): void
{
$this->propagationStopped = true;
}
public function isPropagationStopped(): bool
{
return $this->propagationStopped;
}
}
?>
2 支持通配符监听
<?php
class EventDispatcher
{
public function dispatch(EventInterface $event): void
{
$eventName = $event->getName();
// 先匹配精确的事件名
$this->runListeners($eventName, $event);
// 再匹配通配符
foreach ($this->listeners as $pattern => $listeners) {
if ($this->matchPattern($pattern, $eventName)) {
$this->runListeners($pattern, $event);
}
}
}
private function matchPattern(string $pattern, string $eventName): bool
{
$pattern = preg_quote($pattern, '/');
$pattern = str_replace('\*', '.*', $pattern);
return (bool) preg_match("/^$pattern$/", $eventName);
}
}
// 示例:注册通配符监听器
$dispatcher->addListener('order.*', function(EventInterface $event) {
// 监听所有订单相关事件
});
?>
实用事件调度器实现
<?php
namespace App\EventDispatcher;
class EventDispatcher
{
private array $listeners = [];
private array $eventInstances = [];
private array $sortedEvents = [];
/**
* 注册事件监听器
*/
public function addListener(
string $eventName,
callable $listener,
int $priority = 0
): void {
$this->listeners[$eventName][$priority][] = $listener;
unset($this->sortedEvents[$eventName]); // 清除缓存
}
/**
* 触发事件
*/
public function dispatch(string $eventName, object $event = null): object
{
$event = $event ?? new Event($eventName);
// 调用所有监听器
foreach ($this->getListeners($eventName) as $listener) {
if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) {
break;
}
$listener($event, $eventName, $this);
}
return $event;
}
/**
* 获取按优先级排序的监听器
*/
private function getListeners(string $eventName): array
{
// 检查缓存
if (isset($this->sortedEvents[$eventName])) {
return $this->sortedEvents[$eventName];
}
$matchedListeners = [];
// 查找所有匹配的监听器
foreach ($this->listeners as $listenerEventName => $prioritizedListeners) {
if ($this->matchEventName($listenerEventName, $eventName)) {
foreach ($prioritizedListeners as $priority => $listeners) {
foreach ($listeners as $listener) {
$matchedListeners[$priority][] = $listener;
}
}
}
}
// 按优先级排序
ksort($matchedListeners);
// 扁平化数组
$sortedListeners = [];
foreach ($matchedListeners as $listeners) {
array_push($sortedListeners, ...$listeners);
}
// 缓存结果
$this->sortedEvents[$eventName] = $sortedListeners;
return $sortedListeners;
}
/**
* 移除监听器
*/
public function removeListener(string $eventName, callable $listener): void
{
if (!isset($this->listeners[$eventName])) {
return;
}
foreach ($this->listeners[$eventName] as $priority => $listeners) {
foreach ($listeners as $key => $currentListener) {
if ($currentListener === $listener) {
unset($this->listeners[$eventName][$priority][$key]);
}
}
}
unset($this->sortedEvents[$eventName]);
}
/**
* 事件名称匹配(支持通配符)
*/
private function matchEventName(string $listenerEventName, string $eventName): bool
{
if ($listenerEventName === $eventName) {
return true;
}
if (strpos($listenerEventName, '*') !== false) {
$pattern = str_replace('*', '.*', $listenerEventName);
return (bool) preg_match("/^$pattern$/", $eventName);
}
return false;
}
}
// 基础事件类
class Event
{
protected array $data = [];
public function __construct(string $name = null, array $data = [])
{
$this->data = $data;
}
public function set(string $key, $value): void
{
$this->data[$key] = $value;
}
public function get(string $key, $default = null)
{
return $this->data[$key] ?? $default;
}
}
?>
实际应用示例
<?php
// 订单系统中的应用
class OrderService
{
private EventDispatcher $dispatcher;
public function __construct(EventDispatcher $dispatcher)
{
$this->dispatcher = $dispatcher;
}
public function createOrder($userId, $items): Order
{
// 创建订单
$order = new Order($userId, $items);
// 触发订单创建事件
$this->dispatcher->dispatch('order.created', new Event(null, [
'order' => $order,
'userId' => $userId
]));
return $order;
}
}
// 配置监听器
$dispatcher = new EventDispatcher();
// 发送通知
$dispatcher->addListener('order.created', function(Event $event) {
$order = $event->get('order');
echo "发送订单通知: #{$order->getId()}\n";
}, 10);
// 记录日志
$dispatcher->addListener('order.created', function(Event $event) {
echo "记录订单日志\n";
}, 5);
// 更新库存
$dispatcher->addListener('order.*', function(Event $event) {
echo "处理订单相关事件\n";
});
// 使用
$orderService = new OrderService($dispatcher);
$order = $orderService->createOrder(1, ['product1', 'product2']);
?>
性能优化技巧
<?php
class EventDispatcherOptimized
{
private array $listeners = [];
private array $sortedListeners = [];
private array $wildcardListeners = [];
public function addListener(string $eventName, callable $listener, int $priority = 0): void
{
if (strpos($eventName, '*') !== false) {
$this->wildcardListeners[$eventName][] = ['priority' => $priority, 'listener' => $listener];
} else {
$this->listeners[$eventName][$priority][] = $listener;
}
// 清除相关的缓存
unset($this->sortedListeners[$eventName]);
}
public function dispatch(string $eventName, object $event = null): object
{
$event = $event ?? new Event($eventName);
// 获取并执行监听器
foreach ($this->getListeners($eventName) as $listener) {
$listener($event, $eventName);
}
return $event;
}
private function getListeners(string $eventName): array
{
// 检查缓存
if (isset($this->sortedListeners[$eventName])) {
return $this->sortedListeners[$eventName];
}
$listeners = [];
// 合并精确匹配的监听器
if (isset($this->listeners[$eventName])) {
$listeners = $this->listeners[$eventName];
}
// 合并通配符匹配的监听器
foreach ($this->wildcardListeners as $pattern => $wildcardListeners) {
if ($this->matchWildcard($pattern, $eventName)) {
foreach ($wildcardListeners as $wl) {
$listeners[$wl['priority']][] = $wl['listener'];
}
}
}
// 排序并扁平化
ksort($listeners);
$flattened = [];
foreach ($listeners as $priorityListeners) {
array_push($flattened, ...$priorityListeners);
}
$this->sortedListeners[$eventName] = $flattened;
return $flattened;
}
}
?>
最佳实践建议
- 使用接口而非具体类:定义统一的Event接口
- 惰性加载:对于大型事件系统,考虑按需加载监听器
- 缓存优化:缓存排序结果,避免重复计算
- 错误处理:监听器异常不应影响其他监听器执行
- 可测试性:设计为可注入mock的组件
PHP事件调度器的核心价值在于解耦系统和扩展性,通过事件驱动架构让系统更加灵活、可维护。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播