必须同时开启数据库profiling和日志target的categories过滤才能记录sql;需配置db组件的enableprofiling与enableparamlogging,以及log target中精确匹配yii\db\command::query和execute的categories,并设exportinterval与flushinterval为1确保实时写入。

要让Yii模型查询的SQL语句自动记录到日志文件中,必须同时开启数据库连接层的SQL捕获能力与日志组件的目标导出能力,缺一不可;只配log不启db profiling,或只开profiling不设categories过滤,都会导致SQL完全不出现。
启用数据库SQL捕获
在 config/web.php 的 components → db 配置块内,添加两行关键开关:
'enableProfiling' => true,
'enableParamLogging' => true,
前者让 Yii 记录每条 SQL 的执行耗时和上下文,后者确保绑定参数(如 :id、:name)的真实值也一并写入日志。不加这两项,即使后续日志配置正确,也只会看到带占位符的原始SQL,看不到实际执行时传了什么值。
配置SQL专用日志目标
在 config/web.php 的 components → log → targets 数组中,新增一个 FileTarget:
方法一:按类别精准捕获 DB 执行语句
['class' => 'yii\log\FileTarget',
'levels' => ['trace'],
'categories' => ['yii\db\Command::query', 'yii\db\Command::execute'],
'logFile' => '@runtime/logs/sql.log',
'exportInterval' => 1,
'flushInterval' => 1,],
注意:categories 必须小写且精确匹配,'yii\db\Command::query' 匹配 SELECT 类查询,'yii\db\Command::execute' 匹配 INSERT/UPDATE/DELETE 等写操作;写成 'yii\db\command::query' 或 'YII\DB\COMMAND::QUERY' 均无效。
方法二:通配捕获全部数据库相关日志(含连接、事务、错误)
['class' => 'yii\log\FileTarget',
'levels' => ['trace', 'info'],
'categories' => ['yii\db.*'],
'logFile' => '@runtime/logs/db-full.log',],
该方式会记录更多上下文(如连接建立、事务开始/提交),但体积更大;若仅需查SQL本身,优先选方法一。
确保日志能即时写入磁盘
第一步:确认 runtime/logs/ 目录存在且 Web 进程用户(如 www-data 或 nginx)有写权限;运行 ls -ld @runtime/logs/ 检查权限位是否含 w。
第二步:在 log 组件顶层或该 target 内显式设置缓冲控制:
'exportInterval' => 1,
'flushInterval' => 1,
这两个参数必须同时为 1,否则日志可能滞留在内存中数秒甚至更久才落盘——排查问题时刷新页面却看不到最新SQL,八成是这里卡住了。
第三步:验证 runtime 目录别名是否生效;logFile 必须用 @runtime 开头,写成 'logs/sql.log' 或 '../runtime/logs/sql.log' 会导致静默失败,无任何报错提示。
触发并验证SQL日志生成
步骤一:在控制器中执行一条模型查询,例如:
$users = User::find()->where(['status' => 1])->limit(5)->all();
步骤二:访问对应页面,触发该代码执行。
步骤三:立刻检查 @runtime/logs/sql.log 文件内容,应出现类似格式的记录:
[2026-08-06 21:24:12][trace][yii\db\Command::query] SELECT * FROM `user` WHERE `status` = 1 LIMIT 5
若文件为空,先确认 YII_DEBUG 是否为 true(非调试模式下 trace 级别默认被忽略);再检查是否漏配 enableProfiling 或 categories 拼写错误。











