ci3中应在自定义类构造函数中通过get_instance()->load->database('default', true)获取db实例,或显式注入以支持测试;ci4则必须用service('database')。

CI3 中如何在自定义类里安全获取数据库实例
CodeIgniter 3 的 $this->load->database() 只在控制器、模型、库类(继承 CI_Loader 或被正确加载)中直接可用。如果你写了一个普通 PHP 类(比如 App_helper 或独立的业务类),直接调用会报错:Call to a member function query() on null —— 因为 $this->db 根本没初始化。
正确做法是**不依赖 $this,而是通过 CI 的全局实例获取 DB 对象**:
$CI =& get_instance();
$db = $CI->load->database('default', TRUE); // 第二个参数 TRUE 表示返回对象而非赋给 $CI->db
-
'default'是配置组名,可替换为'slave'等多库配置名 - 必须传
TRUE,否则load->database()默认挂载到$CI->db,但你的类里没有$CI引用,也拿不到 - 不要在构造方法里直接写
$this->db = $this->load->database()—— 普通类没有$this->load
构造方法中传入 DB 实例比“自己加载”更可控
硬编码调用 get_instance() 虽然能跑,但带来隐式依赖、测试困难、无法 mock 数据库行为。更推荐显式注入:
class OrderProcessor
{
protected $db;
public function __construct($db = NULL)
{
$this->db = $db ?: get_instance()->load->database('default', TRUE);
}
}
- 构造时支持传入已存在的
$db实例(比如从控制器传入),方便单元测试或复用连接 - 留了 fallback:没传就自己加载,兼顾兼容性和灵活性
- 避免在构造里做耗时操作(如反复 connect),CI 的 DB 类本身有连接复用机制,
load->database()多次调用只建立一次连接
注意 database.php 配置里的 pconnect 和 save_queries
自定义类频繁创建 DB 实例时,这两个配置会显著影响性能和内存:
-
'pconnect' => FALSE(默认):每次load->database()都新建连接;设为TRUE可复用,但需确认数据库服务器支持且无连接泄漏风险 -
'save_queries' => TRUE(默认):记录所有 SQL,调试有用,但在循环中 new 多个类实例时会快速吃光内存 —— 生产环境建议关掉 - 如果只是读操作,可指定轻量配置组:
$db = get_instance()->load->database('readonly', TRUE),单独配'pconnect'和'cache_on'
CI4 的差异:不能再用 get_instance()
如果你实际用的是 CodeIgniter 4,上面所有基于 get_instance() 的写法都会失败 —— CI4 彻底移除了它。正确方式是使用服务定位器:
use CodeIgniter\Database\Database;
class OrderProcessor
{
protected $db;
public function __construct(Database $db = null)
{
$this->db = $db ?? service('database');
}
}
- CI4 中
service('database')是标准入口,自动复用连接池 - 构造函数类型提示
Database可让 IDE 补全、DI 容器自动注入 - 别试图在 CI4 里仿 CI3 写法,
get_instance()已不存在,硬调会 fatal error
CI3 和 CI4 的 DB 实例获取路径完全不同,看错框架版本是这类问题最常踩的坑。先确认 system/CodeIgniter.php 文件是否存在、版本号是否在注释里标明 —— 别靠文件夹名判断。











