报错时没看到SQL和参数是因为log.level默认仅设['error'],需显式添加'debug'并启用APP_DEBUG=true;Log::record()不能直接传异常对象,应手动提取getMessage()、getTraceAsString()等关键字段并脱敏记录。

报错时没看到 SQL 和参数,是因为日志级别没开够
默认 log.level 配置为 ['error'],只记错误堆栈,不记 SQL、请求参数、变量 dump。想看到「为什么报错」,必须显式开启 debug 级别:
- 在
config/log.php中设置'level' => ['error', 'debug'] - 仅开发环境启用:用
APP_DEBUG => true触发完整调试日志(含 SQL、$_POST、$_GET、路由解析过程) - 生产环境慎用
debug:高频接口开启后会快速撑爆磁盘,且可能泄露敏感字段
Log::record() 不能直接塞异常对象,得手动提取关键字段
Log::record($e) 会把整个 Exception 对象转成字符串,丢失堆栈层级和上下文。真正有用的报错日志要拆开写:
- 用
$e->getMessage()+$e->getTraceAsString()拼接基础信息 - 补上当前请求上下文:
request()->url()、request()->method()、request()->ip() - 关键参数脱敏后再记录:
array_diff_key($request->param(), array_flip(['password', 'token'])) - 避免在
catch块里直接Log::record($e, 'error')—— 它不会自动展开 trace,查问题时还得翻原始异常
SQL 报错没进日志?检查数据库日志开关和驱动兼容性
ThinkPHP 的 SQL 日志不是随错误自动触发的,它依赖两个独立开关:
-
'sql_explain' => true(配置中)—— 仅对EXPLAIN语句生效,不影响报错 -
'log_sql' => true(部分旧版配置项,5.1+ 已移除)→ 实际应靠db.debug控制 - 确认数据库连接配置中启用了
'debug' => true,否则即使报错也不会输出原始 SQL - Pgsql/Sqlite 驱动对
debug支持不一致,MySQL 最稳定;若用 Pgsql 却看不到 SQL,优先换驱动或加try/catch手动捕获$pdo->errorInfo()
自定义错误处理器必须调用 Log::record(),不能只 echo 或 die
用 set_exception_handler() 全局兜底时,常见错误是只打印或跳转,没落地日志:
立即学习“PHP免费学习笔记(深入)”;
- 在自定义 handler 函数里,第一件事是
Log::record(..., 'error', true),第三个参数true强制立即刷盘,防止进程崩溃前日志丢失 - 别把整个
$_SERVER或$_REQUEST直接传进去 —— 体积大、含敏感信息、JSON 化后难 grep - 建议结构固定:
['msg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'sql' => $lastQuery ?? null] - 如果用了队列或异步日志通道(如 Elasticsearch),确保该通道在 handler 中可用 —— 多数通道依赖容器实例,而异常 handler 是裸函数,需提前初始化
最易被忽略的一点:SQL 报错和 PHP 异常是两层。ORM 层抛出的 think\db\exception\DataNotFoundException 会被正常捕获记录,但 PDO 底层的连接超时、权限拒绝等致命错误,可能绕过框架直接由 PHP 报出,此时必须靠 set_error_handler() 补漏,且不能依赖任何框架类 —— 它们可能还没加载完。



















