最常用、最直接的方式是调用getLastSql(),必须在select()、find()、update()等执行方法之后立即调用,否则返回空或上一条;fetchSql(true)可预览未执行的SQL(含?占位符),适合调试拼接逻辑。

最常用、最直接的方式是调用 getLastSql(),但它必须在数据库操作执行之后立即使用,否则可能为空或返回上一条语句。
一、用 getLastSql() 拿已执行的 SQL
这个方法返回的是「真正发给数据库执行过」的那条 SQL(含 ? 占位符),适合验证最终效果。关键点:
- 一定要在
select()、find()、update()、delete()等执行方法之后调用 - 不能写在
where()或order()链式中间,否则 SQL 还没组装完成,会返回空或旧值 - 如果是 Db 类操作:用
Db::getLastSql();如果是模型操作:用$model->getLastSql()或UserModel::getLastSql() - 多数据库连接时(如读写分离),需指定连接名:
Db::connect('read')->getLastSql()
二、用 fetchSql(true) 预览待执行的 SQL
它不真正执行查询,只生成并返回 SQL 字符串,适合调试复杂条件拼接是否正确。注意:
- 必须紧挨着执行方法,比如
->fetchSql(true)->select(),中间不能插with()、cache()等(部分版本会失效) - 返回的是原始预处理语句,例如
WHERE status = ?,不是WHERE status = 1 - 关联查询(
with())下,它一般只返回主表 SQL,子查询不会一并显示
三、开启 SQL 日志全局追踪
适合批量观察、排查慢查询或遗漏的隐式操作。前提条件缺一不可:
立即学习“PHP免费学习笔记(深入)”;
-
app_debug = true(通常在.env或config/app.php中设置) -
log.level包含'sql',例如:['error', 'sql', 'notice'] - 日志文件大小足够:若 SQL 超长被截断(显示为
(2048 bytes)),需调大log.file_size(设为0表示不限制) - 中文/emoji 不乱码:确认
default_charset是utf8mb4,且 MySQL 连接也用了对应字符集
四、快速临时调试小技巧
不用改配置、不依赖日志,适合开发时随手验证:
- 模型中可用简写
->_sql()(ThinkPHP 3.2 及部分 5.x 版本支持),等价于->getLastSql() - 配合
dump()输出更友好:dump(Db::getLastSql()); - 想看到带真实参数的完整 SQL(仅限临时调试):需手动替换 ? 占位符,但注意这不是标准做法,生产环境禁用



















