在codeigniter 3自定义类中,必须通过$ci =& get_instance()获取ci单例并加载数据库,再缓存$this->db属性,才能安全使用select()->from()->where()->get()等链式查询,否则会因db未初始化而报错。

CI自定义类里怎么正确加载并使用DB类做链式查询
CodeIgniter 3 的自定义类(比如放在 application/libraries/ 或 application/helpers/)默认拿不到 $this->db,直接 new 实例或用 get_instance() 是最稳妥的入口。别在构造函数里硬写 $this->load->database() —— 自定义类没 $this->load。
实操建议:
- 用
get_instance()获取 CI 超全局对象,再调用load->database()(只加载一次,可加判断) - 链式调用前确认
db对象已初始化,否则会报Call to a member function select() on null - 如果类要复用,把
db实例缓存到私有属性,避免重复加载
class My_data_handler
{
private $db;
public function __construct()
{
$ci =& get_instance();
$ci->load->database();
$this->db = $ci->db;
}
public function get_active_users()
{
return $this->db->select('id, name, email')
->from('users')
->where('status', 'active')
->get()
->result();
}
}
为什么链式查询在自定义类里常返回空数组或报错
根本原因不是语法错,而是 db 连接未就绪或作用域丢失。CI 的 db 类依赖 CI 核心的配置和驱动初始化流程,跳过 get_instance() 直接 new CI_DB 会导致连接参数缺失、字符集未设置、甚至触发 Undefined property: CI_DB::$active_record 错误。
常见错误现象:
-
Call to a member function from() on null:$this->db为null,没正确赋值 - 查出数据但字段全为
null:字符集或数据库配置没继承,通常因没走 CI 的load->database() - WHERE 条件失效、LIMIT 不生效:底层驱动没启用 Active Record 模式(CI3 默认开启,但手动 new 时不会自动启用)
get_instance() 和 CI =& get_instance() 写法有区别吗
没本质区别,但引用写法更安全。CI 的 get_instance() 返回的是单例引用,$ci =& get_instance() 确保后续对 $ci 的修改(比如加载库、设置属性)能同步回原始实例;而 $ci = get_instance() 在某些 PHP 版本下可能产生副本,导致 $ci->load->database() 加载后,其他地方仍拿不到 $ci->db。
所以统一用引用赋值:
- ✅ 正确:
$ci =& get_instance(); $ci->load->database(); - ❌ 风险:
$ci = get_instance(); $ci->load->database();(尤其在 PHP 7.4+ 的严格模式下易出问题)
链式查询结果怎么统一处理(比如分页、异常兜底)
自定义类里别直接 return result() 或 row(),留出扩展空间。CI 的 get() 返回的是 CI_DB_result 对象,后续方法才真正执行解析逻辑,提前调用会切断链式能力。
实操建议:
- 返回
get()结果对象,让调用方决定是result()、row_array()还是num_rows() - 加一层 try/catch 捕获
Database_Exception,避免数据库挂掉时整个请求崩掉 - 分页不推荐在自定义类里硬编码
limit()+offset(),应接收$limit和$offset参数,由业务层控制
复杂点在于:CI3 的 DB 类本身不校验 SQL 注入风险,所有 where()、like() 参数必须确保来自可信源;如果传入用户输入,务必用 escape_str() 或绑定参数(where('name = ?', $user_input))。











