必须同时开启APP_DEBUG、启用log.php中sql日志级别、确保database.php中trigger_sql=true,否则getLastSql()返回空;验证需dump(config('app.debug'))为true且runtime目录已清空。

要在ThinkPHP 8.0中让模型操作真实打印出执行的SQL语句,必须同时激活调试上下文、启用SQL日志通道、确保数据库监听器生效,缺一不可;否则调用getLastSql()返回空字符串,fetchSql()也仅输出占位符。
确认并强制开启APP_DEBUG环境
打开项目根目录下的.env文件,将APP_DEBUG设为true,等号两侧【不能有空格】:APP_DEBUG=true。
删除整个runtime/目录(不是只删子目录),否则框架仍加载旧缓存配置,config('app.debug')可能返回false。
在任意控制器中临时加入dump(config('app.debug'));,访问该路由验证是否输出true;若为false,说明.env未被加载或存在BOM头——用VS Code另存为“UTF-8 无 BOM”格式。
立即学习“PHP免费学习笔记(深入)”;
配置log.php启用SQL日志级别
打开config/log.php,找到'channels' => ['trace' => [...]]配置段。
确保'level'数组中包含'sql':例如'level' => ['error', 'sql', 'notice'];若缺失,SQL语句不会写入日志,Trace面板里“SQL”标签页将只显示数量,点击后为空。
检查'path'指向的目录(默认runtime/log/)对Web服务器用户可写;权限不足时日志静默失败,无任何报错提示。
启用数据库SQL触发与监听机制
打开config/database.php,确认'trigger_sql' => true已启用(TP8.0默认开启,但若项目曾手动修改过需复查)。
方法一:全局启用
在database.php的连接配置中,确保'trigger_sql' => true位于'default' => [...]或具体连接配置内。
方法二:运行时动态启用
在控制器中获取Db实例后立即调用:Db::connect()->setTriggerSql(true);。这适用于多数据库场景下仅对某连接开启监听。
注意:若项目禁用了事件系统(如自定义了app/provider.php且未注册think\db\Connection::class),查询监听器不会被加载,SQL日志完全不生成。
在模型中打印真实执行SQL的三种方式
第一步:使用fetchSql()预览SQL而不执行
在模型查询链末尾添加->fetchSql(),再调用select()或find(),返回的是SQL字符串而非数据集。
第二步:执行后立刻获取最后一条SQL
执行$user = User::where('id', 1)->find();后,立即调用dump(User::getLastSql());——此方法依赖模型类继承自think\Model且未重写getLastSql逻辑。
第三步:在Db门面中统一捕获
改用Db::name('user')->where('id', 1)->find();后,调用dump(Db::getLastSql());更稳定,避免模型层自定义覆盖导致失效。



















