ThinkPHP6接口日志需在中间件中捕获原始请求体和响应内容:POST/PUT/DELETE用getRawContent(),GET用QUERY_STRING+parse_str();响应通过end()回调获取getContent();日志应含IP、URL、方法、原始参数、状态码、耗时及敏感字段脱敏。

ThinkPHP6 记录接口入参和返回值日志,核心在于“捕获原始数据”和“统一拦截时机”。直接用 input() 或 request()->param() 拿到的是已过滤、已转义、已类型转换后的值,无法用于审计或问题回溯。真正有效的日志必须在框架处理前抓取原始请求体,并在响应发出后获取最终返回内容。
在中间件中统一捕获原始请求参数
中间件是唯一能稳定、早于控制器执行、覆盖全部请求的位置。推荐新建全局中间件(如 LogRequestMiddleware),在 handle() 方法开头执行:
- 对 POST/PUT/DELETE 请求:调用
$request->getRawContent()获取原始 body;若为 JSON,手动json_decode($raw, true)解析,避免依赖input('xxx')反推 - 对 GET 请求:用
$request->server('QUERY_STRING')获取完整查询串,再parse_str()解析,保留原始编码(如+、%20、空格等) - 不推荐仅用
$request->post()或$request->get(),它们虽比input()更接近原始,但仍受 PHP 自动解析影响(如键名转小写、数组自动展开)
记录响应内容需借助中间件的 end 回调
ThinkPHP6 中间件支持 end() 方法,在响应已生成但尚未输出时触发。可在该方法中读取响应对象并提取返回值:
- 判断
$response instanceof \think\Response,再调用$response->getContent()获取原始响应体 - 若返回 JSON,可尝试
json_decode($content, true)提取结构化数据;若失败,保留原始字符串并标记“非 JSON” - 注意:不要在
end()中做耗时操作或输出内容,否则会破坏 HTTP 响应流
日志内容建议包含的关键字段
为便于排查与审计,每条请求-响应日志至少应记录:
立即学习“PHP免费学习笔记(深入)”;
-
基础信息:客户端 IP(
$request->ip())、请求 URL、HTTP 方法、User-Agent、时间戳 -
原始请求快照:GET 参数数组、POST 原始 body(或 JSON 解析后截断前 500 字符)、Header 中关键字段(如
X-Forwarded-For、Authorization) -
响应摘要:状态码、响应耗时(可用
microtime(true)差值)、返回内容类型、JSON 结构中的code和msg(若存在) -
异常标记:若响应含错误码、空数据、超长响应体(如 >1MB)或匹配可疑模式(如
<script></script>、javascript:),额外打标并归类
避开常见陷阱
几个高频踩坑点直接影响日志有效性:
- 别在控制器里手写日志:易遗漏、逻辑分散、无法覆盖异常中断路径(如验证失败抛出异常时控制器未执行)
-
禁用 input() 的 filter 参数做日志源:例如
input('content', '', 'htmlspecialchars')会让真实输入永远丢失,日志里只剩转义结果 -
文件日志注意性能与轮转:高并发下直接写文件可能阻塞,建议用
think\facade\Log::channel('file')->record()并配置 daily 驱动,避免单文件过大 - 敏感字段脱敏再记录:如手机号、身份证号、支付金额、token 等,须在写入日志前正则替换,符合基本安全规范



















