在ThinkPHP6事件中写日志需在监听器handle方法内用Log门面或注入LoggerInterface记录,确保APP_DEBUG配置合理、runtime/log可写、log.php路径明确,并避免敏感数据泄露与上下文缺失。

在 ThinkPHP6 的事件(Event)中写入运行日志,核心是确保事件触发时能安全、结构化地调用日志服务。事件本身不直接处理日志,但你可以在监听器(Listener)或订阅器(Subscriber)的 handle 方法里使用 Log 门面或注入的 LoggerInterface。
确认日志基础可用
确保项目已启用日志功能且配置正确:
- APP_DEBUG 必须为 false(线上环境),否则错误类日志可能不落盘;开发阶段可设为 true,但 info/warning 级别仍可记录
-
runtime/log/ 目录存在且 Web 进程有写权限,如 Linux 下执行
chmod -R 755 runtime/log -
log.php 配置中 channels.file.path 不为空,推荐显式指定:
'path' => 'log/'(相对于 runtime/)
在事件监听器中写日志
假设你已定义一个事件 UserLoginSuccess,并创建了监听器 LogUserLoginListener:
- 在
app/listener/LogUserLoginListener.php中引入门面:use think\facade\Log; - 在
handle()方法内按需记录,例如:
注意:不要在监听器中使用 exit 或未捕获异常中断流程,否则日志可能无法写入(TP6 默认延迟写入,请求结束才刷盘)。
立即学习“PHP免费学习笔记(深入)”;
用依赖注入方式更规范
如果监听器支持构造函数注入(如通过容器绑定),推荐使用 PSR-3 兼容的 LoggerInterface:
- 在监听器类构造方法中声明:
public function __construct(LoggerInterface $logger) - 保存为属性
$this->logger,后续调用$this->logger->info(...) - 这种方式利于测试和替换日志驱动,也符合框架设计原则
避免常见陷阱
事件日志容易出问题的几个点:
-
敏感数据泄露:不要直接
Log::info(json_encode($_POST)),应过滤 password、token 等字段 -
上下文缺失:事件中无法直接访问
$request或$auth,需在触发事件前把必要信息传入事件对象(如new UserLoginSuccess($user, $ip, $ua)) - 异步事件不保证日志实时可见:若用队列异步分发事件,日志会写入队列消费进程的 runtime/log/,而非当前 HTTP 请求的目录
-
忽略日志级别配置:检查
config/log.php中'level'是否包含你使用的级别(如['info','warning']),否则 info 日志会被静默丢弃



















