CodeIgniter 必须通过 $this->load->model() 加载模型,模型名转为小驼峰属性(如 user_model),直接 new 或未加载会导致“Call to a member function on null”;数据库操作强制在模型中封装,控制器仅调度;CI3 需显式调用 result_array(),CI4 模型返回默认为数组。

控制器里用 $this->load->model() 加载模型再调用方法
CodeIgniter 不允许直接 new 模型实例(除非你绕过框架机制),必须通过 $this->load->model() 加载。加载后,模型名会自动变成小驼峰形式的属性名,比如 user_model 加载后是 $this->user_model,然后才能调用它的方法。
常见错误现象:Call to a member function get_user() on null,基本就是忘了 load->model() 或拼错了模型文件名(CI3 要求文件名和类名完全一致,且首字母小写)。
- 模型文件必须放在
application/models/下,例如application/models/User_model.php - 类名必须是
User_model(注意下划线),且继承CI_Model - 加载时传入字符串不带
.php后缀,也不含路径,如$this->load->model('user_model') - 如果模型在子目录,比如
application/models/admin/Log_model.php,则写成$this->load->model('admin/log_model')
$this->db 不能在控制器里直接用,查数据逻辑必须进模型
CI 的 MVC 约束很明确:控制器只负责调度、接收输入、传递参数、渲染视图;所有数据库操作(哪怕只是一行 select * from user)都得封装进模型方法。这不是可选项,而是框架设计强制的分层逻辑。
容易踩的坑:$this->db->get('user')->result() 写在控制器里看似能跑通,但一旦要加条件、换表、做 JOIN 或改数据库驱动,就得到处改控制器——模型层就白建了。
- 模型里用
$this->db->where()、$this->db->join()等构造查询,最后返回$query->result()或$query->row() - 控制器只管传参、接返回值、塞进
$data交给视图:$data['users'] = $this->user_model->get_all(); - 如果查的是关联数据(比如用户+订单),模型里用
join()一次性查完,别在控制器里循环查
模型方法怎么接收并处理控制器传来的参数
控制器调用模型方法时传参,和普通 PHP 函数一样,但要注意过滤和默认值。CI 自带的 $this->input 类不能在模型里直接用,所有外部输入必须由控制器“洗干净”再交过去。
典型场景:URL 带 ?status=active,控制器取值后传给模型:
$status = $this->input->get('status') ?: 'all';$data = $this->user_model->get_by_status($status);
模型里就专注查,不碰输入源:
public function get_by_status($status) { if ($status === 'all') { return $this->db->get('user')->result(); } return $this->db->where('status', $status)->get('user')->result();}
- 不要在模型里调
$this->input->get()—— 违反单一职责,也导致单元测试困难 - 参数类型要预判:ID 是整数?状态是字符串?空值怎么处理?模型方法开头加个
if (empty($id)) return [];很常见 - 模糊搜索这类动态条件,建议用数组传参,比一堆布尔开关更易维护
CI3 和 CI4 在模型调用上最明显的区别
CI4 把模型升级为独立服务类,默认支持命名空间、自动连接数据库、内置分页和软删除。而 CI3 的模型几乎只是个壳,$this->db 需手动加载,query() 返回的对象必须显式调 result_array() 才能拿到数组——这点新手最容易卡住。
CI3 示例(不加 result_array() 就是对象,不是数组):
$query = $this->db->get('user');return $query->result_array(); // ✅// return $query; ❌ 控制器收到的是 CI_DB_result 对象,foreach 会报错
CI4 示例(Model 类自带 findAll()、find(),返回直接是数组或对象):
class User_model extends Model { protected $table = 'user'; }// 控制器里:$users = $this->user_model->findAll(); // 直接是数组
- CI3 中
$this->db->query($sql)->result_array()是标配,漏掉就会调试半天 - CI4 的模型类若没显式定义
$table,find()会报错,不是静默失败 - 跨版本迁移时,CI3 的模型方法名(如
get_user_by_id())在 CI4 里建议改用标准方法名(find($id))以利升级
实际写的时候,最常被忽略的是模型方法的返回值类型一致性——要么全用 result() 返回对象,要么全用 result_array() 返回数组,混着用会让控制器的 foreach 和 isset() 判断变得脆弱。


















