CI3中模型必须在控制器中显式加载,如$this->load->model('User_model'),否则调用方法报错;模型只处理数据逻辑,参数由控制器传入;CI4改用model()函数或服务定位器。

模型必须在控制器里显式加载,否则调用方法会报 Call to undefined method —— 这不是配置问题,是执行顺序问题。
控制器里怎么加载模型才不会报错
最常见错误是:写了 $this->User_model->get(),但没提前调用 $this->load->model('User_model')。CI 不会自动发现并加载模型类,必须手动触发。
- 只在某个方法里用一次?直接在方法开头写:
$this->load->model('User_model'); - 整个控制器都要用?在
__construct()里加载,并确保先调parent::__construct() - 模型在子目录下(如
models/auth/Permission_model.php)?路径用斜杠:$this->load->model('auth/Permission_model'); - CI4 完全不同:不用
$this->load->model(),而是用use+new或服务定位器:model('UserModel')
模型方法该接收什么参数
模型不该自己读 $this->input->post() 或解析 URL 参数 —— 那是控制器的职责。模型只处理数据逻辑,输入必须由控制器准备好后传入。
- 错的做法:
function insert_user() { $data = ['name' => $this->input->post('name')]; ... } - 对的做法:
function insert_user($data) { return $this->db->insert('users', $data); } - 批量操作也一样:控制器组装好数组,模型只负责执行插入或更新
- 需要条件查询时,传 ID、slug 或 where 数组,别在模型里硬编码
WHERE id = 123
CI4 模型里 $useTimestamps 为什么总插出 0
不是时间没获取到,是字段类型和配置不匹配。MySQL 的 DATETIME 字段必须配合 $useTimestamps = true,否则 CI4 默认写入 0000-00-00 00:00:00。
- 确认表里有
created_at和/或updated_at字段,类型为DATETIME或TIMESTAMP - 模型中必须声明:
protected $useTimestamps = true; - 如果字段名不是默认的,要同时指定:
protected $createdField = 'add_time'; - 字段不存在?把
$useTimestamps设为false,否则插入失败或静默丢弃时间值
等级计算、状态变更这类逻辑放哪
一定放在模型里,而且要用事务包裹。控制器里写一句 $this->User_rank_model->update_rank($user_id) 就完事 —— 多处触发(签到、发帖、充值)时,逻辑不会散落各处,也不会漏掉日志或通知。
- 别在控制器里查成长值、再查等级表、再判断升几级:耦合高,没法复用
- 模型里预加载等级配置(
$this->rank_levels),用二分查找比foreach快得多 - 降级也要处理:VIP 掉级时取消特权,不是只做“升级成功”提示
- 并发风险真实存在:同一用户短时间内多次积分变动,可能触发两次等级更新,得靠数据库行锁或应用层防重
模型不是数据库语句的搬运工,它是业务规则的容器。传什么、查什么、改什么、是否事务、是否通知——这些决策点一旦写进控制器,后面维护的人就得反复猜意图。


















