SQL日志没输出?先确认APP_DEBUG=true且APP_ENV=local,否则Laravel默认禁用查询日志;DB::enableQueryLog()仅对当前请求生效,DB::listen()更适合实时捕获全量SQL。

SQL日志没输出?先确认 APP_DEBUG 是 true
Laravel 只有在 APP_DEBUG=true 且环境为本地(APP_ENV=local)时,才会默认启用查询日志。如果改过配置或部署到测试环境,DB::enableQueryLog() 也可能被忽略——它只对当前请求生效,且不自动打印。
检查方式:php artisan tinker 中运行 config('app.debug') 和 config('app.env'),确保两者都符合要求。
- 线上环境切勿开启
APP_DEBUG=true,否则会暴露敏感 SQL 和堆栈 -
APP_ENV=production下即使手动调用DB::enableQueryLog(),DB::getQueryLog()也常返回空数组——这是 Laravel 的硬性限制 - 部分云服务(如 Laravel Vapor、Forge 部署)会覆盖 .env,需检查实际加载的配置
想看实时 SQL?用 DB::listen() 替代轮询 getQueryLog()
DB::getQueryLog() 是快照式读取,只捕获调用前已执行的语句;而 DB::listen() 是事件监听,能捕获所有后续查询,适合调试中间件、命令行脚本或异步任务。
示例:在 AppServiceProvider::boot() 中加入
use Illuminate\Support\Facades\DB;
DB::listen(function ($event) {
\Log::info('SQL: ' . $event->sql, [
'bindings' => $event->bindings,
'time' => $event->time,
]);
});
-
$event->bindings是参数化值,避免直接拼接日志导致 SQL 注入误报 - 若日志中出现
? ? ?却没看到实际值,说明你用了DB::raw()或原生查询,绑定参数未生效 - 该监听对所有数据库连接生效,多库场景下可通过
$event->connectionName过滤
日志太长刷屏?用 DB::enableQueryLog() + 条件截断
在控制器或命令中临时启用,配合简单判断控制输出量:
DB::enableQueryLog();
// ... 执行若干查询
$queries = DB::getQueryLog();
if (count($queries) > 50) {
$queries = array_slice($queries, -20); // 只留最后 20 条
}
\Log::debug('Recent queries', $queries);
-
enableQueryLog()不影响性能(除非大量查询),但内存占用随查询数线性增长 - 分页查询(
paginate())会触发额外的 COUNT 查询,容易让日志膨胀,可提前DB::disableQueryLog()关闭 - Eloquent 的
toSql()方法不执行查询,仅生成 SQL 字符串,适合验证语法,但看不到绑定值和执行时间
Log 输出乱码或字段缺失?检查 logging.php 的 channel 配置
Laravel 默认用 stack channel,底层可能走 daily 或 single。如果 SQL 日志没进文件,常见原因是:
-
channels.daily的tap数组里加了自定义 Formatter,但没处理数组结构的日志上下文(如bindings) -
LOG_LEVEL=error导致info级别日志被过滤,应设为debug或info - 使用
Monolog\Handler\StreamHandler时,路径权限不足,日志写入失败但无提示
快速验证:在路由中写 Log::info('test', ['foo' => 'bar']);,看是否进日志文件。如果这个都不行,问题不在 SQL,而在整个日志管道。


















