PHP 怎么PHP 事件响应

wen PHP项目 3

本文目录导读:

PHP 怎么PHP 事件响应

  1. 直接回调函数(最简单的“事件”)
  2. 面向对象的事件分发器(自定义类)
  3. 使用 SplSubject / SplObserver(PHP 内置观察者模式)
  4. 使用 Symfony EventDispatcher 组件(推荐生产环境)
  5. 使用事件驱动框架(如 Workerman / Swoole)
  6. 总结:如何选择?

在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();

这里 onConnectonMessageonClose 就是预定义的事件。


如何选择?

场景 推荐方式
简单的回调逻辑 直接回调函数
中等复杂度,需要解耦 自定义 EventDispatcher 或 SplObserver
生产级系统,框架已有 使用框架自带事件(Laravel Event、Symfony EventDispatcher)
常驻内存应用(长连接) Workerman、Swoole 内置事件

如果你是新手,建议从 自定义 EventDispatcher 开始理解核心概念,然后过渡到框架中的事件系统。

抱歉,评论功能暂时关闭!