本文目录导读:

- 直接回调函数(最简单的“事件”)
- 面向对象的事件分发器(自定义类)
- 使用 SplSubject / SplObserver(PHP 内置观察者模式)
- 使用 Symfony EventDispatcher 组件(推荐生产环境)
- 使用事件驱动框架(如 Workerman / Swoole)
- 总结:如何选择?
在PHP中实现“事件响应”机制,通常有几种不同的方式,具体取决于你的使用场景(是简单的回调、面向对象的事件驱动,还是使用现有框架的事件系统)。
以下从 基础到高级 介绍几种常见实现方式:
直接回调函数(最简单的“事件”)
这是最朴素的方式,将函数名或匿名函数作为参数传递。
<?php
// 定义一个“事件触发点”
function onUserLogin($username, $callback) {
echo "用户 {$username} 登录了。\n";
// 执行回调(模拟事件响应)
if (is_callable($callback)) {
call_user_func($callback, $username);
}
}
// 定义事件响应函数
function sendWelcomeEmail($user) {
echo "发送欢迎邮件给 {$user}\n";
}
// 使用:调用事件并传入响应
onUserLogin("Alice", 'sendWelcomeEmail');
// 也可以使用匿名函数
onUserLogin("Bob", function($user) {
echo "记录登录日志:{$user}\n";
});
面向对象的事件分发器(自定义类)
更结构化的方式,适用于插件系统或复杂应用。
<?php
class EventDispatcher {
private $listeners = [];
// 注册事件监听器
public function on($eventName, callable $listener) {
$this->listeners[$eventName][] = $listener;
}
// 触发事件
public function dispatch($eventName, $data = null) {
if (isset($this->listeners[$eventName])) {
foreach ($this->listeners[$eventName] as $listener) {
call_user_func($listener, $data);
}
}
}
}
// 使用
$dispatcher = new EventDispatcher();
// 注册监听
$dispatcher->on('user.registered', function($user) {
echo "新用户注册:{$user['name']}\n";
});
$dispatcher->on('user.registered', function($user) {
echo "发送验证邮件到:{$user['email']}\n";
});
// 触发事件
$dispatcher->dispatch('user.registered', ['name' => 'Alice', 'email' => 'alice@example.com']);
优点:解耦,灵活添加/移除监听器。
使用 SplSubject / SplObserver(PHP 内置观察者模式)
PHP SPL 提供了标准的观察者模式接口,适用于一对多的依赖关系。
<?php
// 被观察者(事件源)
class User implements SplSubject {
private $observers = [];
public $name;
public function __construct($name) {
$this->name = $name;
}
public function attach(SplObserver $observer) {
$this->observers[] = $observer;
}
public function detach(SplObserver $observer) {
$index = array_search($observer, $this->observers, true);
if ($index !== false) {
unset($this->observers[$index]);
}
}
public function notify() {
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
// 模拟登录事件
public function login() {
echo "{$this->name} 登录了\n";
$this->notify(); // 触发通知所有观察者
}
}
// 观察者(事件响应者)
class Logger implements SplObserver {
public function update(SplSubject $subject) {
echo "记录日志:{$subject->name} 登录\n";
}
}
class Mailer implements SplObserver {
public function update(SplSubject $subject) {
echo "发送邮件给:{$subject->name}\n";
}
}
// 使用
$user = new User("Alice");
$user->attach(new Logger());
$user->attach(new Mailer());
$user->login(); // 自动触发所有观察者
使用 Symfony EventDispatcher 组件(推荐生产环境)
最流行的PHP事件系统之一,Laravel、Drupal等核心也借鉴了这种思路。
安装:
composer require symfony/event-dispatcher
使用示例:
<?php
require 'vendor/autoload.php';
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
// 1. 定义自定义事件类(可选)
class UserRegisteredEvent extends Event {
const NAME = 'user.registered';
public $user;
public function __construct($user) {
$this->user = $user;
}
}
// 2. 创建调度器
$dispatcher = new EventDispatcher();
// 3. 注册监听器
$dispatcher->addListener(UserRegisteredEvent::NAME, function(UserRegisteredEvent $event) {
echo "发送欢迎邮件给:{$event->user['name']}\n";
});
$dispatcher->addListener(UserRegisteredEvent::NAME, function(UserRegisteredEvent $event) {
echo "记录注册日志\n";
});
// 4. 触发事件
$event = new UserRegisteredEvent(['name' => 'Alice', 'email' => 'alice@example.com']);
$dispatcher->dispatch($event, UserRegisteredEvent::NAME);
使用事件驱动框架(如 Workerman / Swoole)
对于 常驻内存 的PHP应用(如WebSocket、TCP服务),事件响应是核心模式。
// 伪代码示例(Workerman)
$worker = new Worker('websocket://0.0.0.0:8080');
$worker->onConnect = function($connection) {
echo "新连接\n";
};
$worker->onMessage = function($connection, $data) {
echo "收到消息: $data\n";
$connection->send('已收到');
};
$worker->onClose = function($connection) {
echo "连接关闭\n";
};
Worker::runAll();
这里 onConnect、onMessage、onClose 就是预定义的事件。
如何选择?
| 场景 | 推荐方式 |
|---|---|
| 简单的回调逻辑 | 直接回调函数 |
| 中等复杂度,需要解耦 | 自定义 EventDispatcher 或 SplObserver |
| 生产级系统,框架已有 | 使用框架自带事件(Laravel Event、Symfony EventDispatcher) |
| 常驻内存应用(长连接) | Workerman、Swoole 内置事件 |
如果你是新手,建议从 自定义 EventDispatcher 开始理解核心概念,然后过渡到框架中的事件系统。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播