ThinkPHP6.0记录请求日志最可靠方式是自定义中间件,在路由匹配完成后、控制器执行前统一捕获用户ID、模块、动作、参数(脱敏)、IP等结构化字段,注册为全局或路由级中间件,避开静态资源与免日志路径,并写入带索引的日志表或加锁分时JSON文件。

在 ThinkPHP6.0 中,记录请求日志最可靠的方式是通过自定义中间件,在请求进入控制器前统一捕获关键上下文,并结构化写入(数据库或文件)。不能依赖 Log::record() 或零散的 Log::write(),它们缺乏用户身份、参数、IP 等审计必需字段。
中间件位置必须选对
要在「路由匹配完成、控制器执行之前」拿到完整请求信息。中间件的 handle() 方法天然满足这一时序,比在控制器里写日志更稳定、不遗漏。
- 注册为全局中间件(
app/middleware.php),或按需绑定到 admin 路由分组 - 避开静态资源(
.js/.css)、健康检查接口(如/api/ping)、登录登出等免日志路径 - 用
in_array($request->action(), ['login', 'logout', 'captcha'])主动跳过敏感低价值操作
关键字段要主动提取,别靠猜
URL 解析不可靠,$_SERVER 不完整,必须用框架原生方法获取结构化数据:
-
管理员 ID:优先调
$auth->getUserID()(已集成 think-auth);否则封装校验逻辑,检查 session 中的admin_info是否存在且状态有效,不只判session('admin_id') -
模块/控制器/动作:用
$request->rule()->getModule()、getController()、$request->action(),不是$request->method() -
参数:用
$request->param()获取,但必须过滤敏感键(如password、token、old_password),再 JSON 编码存入params字段 -
IP 和 UA:用
$request->ip()和$request->header('user-agent'),避免直接读$_SERVER
存储方式决定可查性
日志表设计不当,后期根本没法查。别用单个 content TEXT 字段存整条 JSON:
- 建表至少包含:
admin_id(INT,关联用户)、module、controller、action、method(GET/POST)、ip、params(JSON 类型或 TEXT)、created_at - 给
admin_id、created_at、module加联合索引,支撑按人、按时间、按模块快速筛选 - 写库逻辑必须包裹
try...catch,失败仅记 error_log,绝不中断主流程
文件存储要防并发丢行
若暂用文件落盘(如测试环境),必须加锁并规范格式:
- 每条日志一行标准 JSON:
json_encode($logData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n" - 写入前用
flock($fp, LOCK_EX)加独占锁,避免多请求同时写导致内容错乱或丢失 - 按天分文件(如
20261029.log),目录按月归档(202610/),防止单目录文件过多
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











