ThinkPHP 6.0事件系统可解耦用户注册后的邮件发送、日志记录与第三方同步逻辑:定义继承think\Event的UserRegistered事件类,编写不依赖构造注入的监听器(如SendWelcomeEmail),在app/event.php中配置监听关系,并在控制器中显式调用Event::trigger触发。

用户注册成功后要发邮件、记日志、同步第三方,但又不想让控制器塞满杂乱代码——得用ThinkPHP 6.0事件系统把主流程和周边动作彻底剥离开,让每段逻辑各守其位、互不干扰。
定义必须继承think\Event的事件类
运行命令行:php think make:event UserRegistered
打开生成的 app/event/UserRegistered.php 文件,删掉默认内容,重写为:
namespace app\event;
use think\Event;
class UserRegistered extends Event {
public $user;
public $ip;
public function __construct($user, $ip = '') {
$this->user = $user;
$this->ip = $ip;
}
}
立即学习“PHP免费学习笔记(深入)”;
【不继承think\Event会导致监听器静默失效,且无任何报错提示】
public 属性名将直接映射为监听器 handle() 方法的参数名,拼错一个字母就完全不执行。
编写监听器并手动获取依赖
运行命令:php think make:listener SendWelcomeEmail
编辑 app/listener/SendWelcomeEmail.php,在 handle() 方法中接收参数,不要写构造函数:
namespace app\listener;
use app\event\UserRegistered;
use think\Mail;
class SendWelcomeEmail {
public function handle($user, $ip) {
$mail = app()->make(Mail::class);
$mail->to($user->email)->send("欢迎注册,您的IP是 {$ip}");
}
}
监听器默认不走容器自动注入,构造函数里传依赖会是 null。所有服务都得在 handle() 里用 app()->make() 或 app('cache') 主动拿。
这一步操作起来很简单,直接把依赖调用写进方法体就行。
统一注册监听器(推荐配置式)
打开 app/event.php,返回一个关联数组:
return [
'app\event\UserRegistered' => [
['app\listener\SendWelcomeEmail', 'handle'],
['app\listener\RecordRegisterLog', 'handle'],
['app\listener\SyncToThirdParty', 'handle']
],
];
键必须是事件类完整命名空间,值必须是二维数组,每个子数组格式为 [监听器类全限定名, 方法名]。
【值不能为字符串,否则监听器不会被触发】
同一事件绑定多个监听器时,按数组顺序执行;若需控制先后,改用 priority 参数动态注册。
在业务完成点显式触发事件
在用户注册成功的控制器方法末尾添加:
Event::trigger(new UserRegistered($user, $ip));
事件不会自己发生,必须手动 trigger。传入事件实例后,框架自动提取 public 属性,按名称匹配传给各监听器 handle() 方法。
CLI 或队列任务中触发前,需先执行 app()->initialize() 补全上下文,否则 app/event.php 配置不生效。
事件名区分大小写,通配符(如 user.*)默认不支持,需额外扩展才可用。



















