自定义库中 $this->db 为 null 是因未继承 ci_controller,db 实例未自动注入;须通过 get_instance() 获取 ci 实例后加载并访问 db 属性。

CI 自定义库中不能直接用 $this->db,必须通过 CI 的单例实例获取 DB 对象。
为什么自定义库里 $this->db 是 null?
CI 的 $this->db 是控制器(CI_Controller)实例的属性,只在控制器及其子类(如模型、视图)中自动注入。自定义库(libraries/ 下的类)不继承 CI_Controller,也没有自动加载 DB 实例,所以直接访问 $this->db 会报错或返回 null。
- 常见错误现象:
Call to a member function query() on null或Trying to get property 'query' of non-object - 不是“没加载 DB”,而是“没把 DB 实例传进来”
- 即使在库构造函数里调用
$this->load->database(),也不会自动挂载到$this上
正确获取 DB 实例的两种方式
推荐使用 CI 的全局引用机制,避免手动传参或重复初始化:
- 用
get_instance()获取当前 CI 实例,再取db属性:$CI =& get_instance(); $CI->load->database(); // 确保已加载(若 autoload 未配) $query = $CI->db->query('SELECT * FROM users'); - 如果库需要频繁操作数据库,可在构造函数里缓存 DB 实例:
public function __construct() { $CI =& get_instance(); $CI->load->database(); $this->db = $CI->db; }之后就能用$this->db->insert()等方法 - 不建议在库中调用
new CI_DB()—— 会绕过 CI 的连接池、配置加载、Active Record 初始化等机制,易出兼容性问题
autoload 配置对自定义库没用
即使你在 application/config/autoload.php 中设置了:
$autoload['libraries'] = array('database');它只对控制器生效,不会自动让自定义库获得 $this->db。- DB 类加载后,仍需通过
get_instance()显式获取引用 - 如果库被多个控制器调用,每次都要走
get_instance(),但这是安全且轻量的——CI 内部是引用传递,不是重复实例化 - 注意:某些老版本 CI(如 2.x)中
get_instance()返回的是引用,CI 3+ 已统一为引用,无需加&,但保留更稳妥
容易忽略的坑:事务与连接生命周期
自定义库中开启事务后,若控制器未显式提交或回滚,可能造成连接残留或事务意外提交:
- 不要在库中单独调用
$this->db->trans_begin()后就返回——控制器层必须配套处理 - 更稳妥的做法:把 DB 操作封装成原子方法,由控制器统一控制事务边界
- 若库内需独立事务(如日志写入失败不影响主流程),务必用
$this->db->trans_strict(FALSE)并手动trans_complete() - 连接关闭由 CI 在请求结束时自动处理,库中无需也不该调用
$this->db->close()
最常被跳过的一步是确认 get_instance() 后是否真正触发了 DB 加载——尤其当你的库在模型或钩子中被提前调用时,$CI->load->database() 必须显式执行,不能依赖 autoload 的时机。











