CI3中$this->db->queries为空的主因是db_debug=FALSE、查询命中缓存、SQL语法错误致执行失败、或提前访问未初始化的$db对象;正确调试需在查询后立即调用last_query(),CI4则需编译SQL并手动替换绑定参数。

直接看 $this->db->queries 数组或 $this->db->last_query() 是最常用、最轻量的方式,但前提是配置和执行时机都对——否则数组为空、返回空字符串、甚至报错都不奇怪。
CI3 中 $this->db->queries 为什么总是空?
不是“没开启日志”,而是查询根本没进数组。常见原因有:
-
db_debug => FALSE:必须设为TRUE(仅限开发环境),否则框架跳过记录逻辑 - 查询被缓存命中:
$this->db->cache_on()开启后,缓存返回数据不触发真实查询,$this->db->queries不追加 - SQL 语法错误导致执行失败:CI3 只把成功执行的语句写入
$this->db->queries,错误语句只进$this->db->query_errors - 提前访问:在
$this->load->database()之前、或模型构造函数里就调$this->db->queries,此时$this->db对象未完全初始化
CI3 查看最后一条 SQL 的正确姿势
$this->db->last_query() 返回的是字符串,适合单步调试,但要注意它只反映最近一次成功执行的语句:
- 必须在查询之后立即调用,比如
$this->db->get('users');后马上跟var_dump($this->db->last_query()); - 如果中间穿插了事务操作(
$this->db->trans_start())、缓存开关或额外查询,结果会被覆盖 - 不包含绑定参数值,看到的是带问号的原始语句,如
SELECT * FROM users WHERE id = ?
CI4 怎么拿到完整可执行的 SQL?
CI4 没有 $this->db->queries 这种全局数组,得靠编译 + 绑定手动拼接:
- 先用
$builder->getCompiledSelect()(或其他getCompiled*方法)拿到带占位符的 SQL - 再用
$builder->getBinds()获取绑定参数数组 - 手动替换占位符,例如用
str_replace()或vsprintf()(注意类型转换,字符串要加引号) - 更稳妥的做法是注册 DBQuery 事件监听,在
app/Config/Events.php里捕获$event['sql']和$event['binds'],直接写入日志文件
真正容易被忽略的点是:CI3 的 db_debug 只影响页面底部显示和 $this->db->queries 记录,它不控制错误是否写入日志文件;而 CI4 的 DBDebug(注意大小写)只影响错误堆栈里是否显示 SQL,跟查询日志完全无关。查错前先分清你到底想定位“执行失败”还是“语句不对”。


















