本文目录导读:

在 PHP 中,“事件”并不是语言内置的核心特性(不像 JavaScript 或 C# 那样),PHP 本身没有原生的 event 关键字或 addEventListener 函数。
我们可以通过 设计模式(如 观察者模式、事件驱动架构)或 第三方库(如 Symfony EventDispatcher)来实现“事件”的效果。
下面从 原生 PHP 手动实现 和 使用组件 两个角度说明。
手动实现简单的事件系统(观察者模式)
这是最基础的方式,适合理解原理。
1 定义事件类
<?php
class Event
{
protected $listeners = [];
// 注册监听器
public function on(string $eventName, callable $callback)
{
$this->listeners[$eventName][] = $callback;
}
// 触发事件
public function trigger(string $eventName, $data = null)
{
if (isset($this->listeners[$eventName])) {
foreach ($this->listeners[$eventName] as $callback) {
$callback($data);
}
}
}
}
2 使用示例
$event = new Event();
// 注册“用户注册成功”事件
$event->on('user.registered', function($user) {
echo "发送欢迎邮件给:" . $user['email'] . PHP_EOL;
});
$event->on('user.registered', function($user) {
echo "记录日志:" . $user['name'] . " 注册成功" . PHP_EOL;
});
// 模拟用户注册,触发事件
$user = ['name' => 'Alice', 'email' => 'alice@example.com'];
$event->trigger('user.registered', $user);
输出:
发送欢迎邮件给:alice@example.com
记录日志:Alice 注册成功
这就是最朴素的“事件”,完全由你自己控制流程。
使用第三方事件库:Symfony EventDispatcher
这是 PHP 生态中最主流、最规范的事件方案,很多框架(如 Laravel、Symfony、Drupal)都基于它。
1 安装
composer require symfony/event-dispatcher
2 定义事件类
use Symfony\Contracts\EventDispatcher\Event;
class UserRegisteredEvent extends Event
{
const NAME = 'user.registered';
public function __construct(public array $user) {}
}
3 编写监听器
class SendWelcomeEmailListener
{
public function __invoke(UserRegisteredEvent $event)
{
echo "发送邮件给:" . $event->user['email'] . PHP_EOL;
}
}
class LogUserRegistrationListener
{
public function __invoke(UserRegisteredEvent $event)
{
echo "记录日志:" . $event->user['name'] . " 注册" . PHP_EOL;
}
}
4 注册与触发
use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); // 注册监听器 $dispatcher->addListener(UserRegisteredEvent::NAME, new SendWelcomeEmailListener()); $dispatcher->addListener(UserRegisteredEvent::NAME, new LogUserRegistrationListener()); // 触发事件 $user = ['name' => 'Bob', 'email' => 'bob@example.com']; $dispatcher->dispatch(new UserRegisteredEvent($user), UserRegisteredEvent::NAME);
输出:
发送邮件给:bob@example.com
记录日志:Bob 注册
优势:支持优先级、订阅器(Subscriber)、事件传播停止(stopPropagation),适合大型项目。
Laravel 中的事件(最常用场景)
如果你在使用 Laravel,它内置了完善的事件系统,基于 Symfony EventDispatcher 封装。
php artisan make:event UserRegistered php artisan make:listener SendWelcomeEmail --event=UserRegistered
触发事件
event(new UserRegistered($user));
或使用 Event Facade:
Event::dispatch(new UserRegistered($user));
Laravel 还支持队列驱动的事件监听,适合发邮件等耗时操作。
是否应该用“事件”?适用场景
| 场景 | 推荐做法 |
|---|---|
| 简单的回调、钩子 | 手动实现观察者模式或直接函数回调 |
| 中等规模项目(无框架) | 引入 symfony/event-dispatcher |
| Laravel / Symfony 项目 | 使用框架自带事件系统 |
| 超大型微服务架构 | 考虑消息队列(RabbitMQ、Kafka)实现事件驱动 |
常见误区
- PHP 没有 “事件循环”:除非你使用 Swoole 或 ReactPHP,否则 PHP 的每个请求结束后所有变量销毁,事件仅限于单次请求生命周期内。
- 事件不是异步的:默认情况下 PHP 的事件监听器是 同步阻塞 执行的,要实现异步,需结合进程或消息队列。
| 方法 | 复杂度 | 适用项目 |
|---|---|---|
| 手动实现(观察者模式) | 低 | 学习/小工具 |
| Symfony EventDispatcher | 中 | 中型 PHP 项目 |
| Laravel 事件系统 | 中 | Laravel 项目 |
| Swoole + 自定义事件 | 高 | 高性能网络应用 |
一句话:PHP 没有原生事件关键字,但通过观察者模式或第三方库可以轻松实现事件机制。