ci_model类不提供通用crud方法,需继承封装create()等操作以提升维护性、数据一致性和安全性,基类应定义表名、自动加载db、统一返回格式并强制校验规则。

CI_Model 类本身不提供开箱即用的通用 CRUD 方法,但你可以通过继承它并封装常用操作来避免重复写 insert()、update()、get_where() 等调用。这种封装不是框架内置功能,而是开发者主动抽象的结果——它有效,但必须自己控制参数边界和错误路径。
为什么不能直接在控制器里用 $this->db->insert() 就完事?
能,但不推荐长期这么做。问题不在语法,而在维护性:
- 每张表都重写一遍字段校验、空值过滤、时间戳填充逻辑,容易漏或不一致
-
where()条件拼错、limit(1)忘加、order_by()写反,这类低级错误在控制器里散落时极难排查 - 事务包裹(
trans_start()/trans_complete())如果只在某几个控制器里加,其他地方没加,数据一致性就成隐患 - 模型本该承担“数据契约”角色,比如
user_status只允许 0/1/2,这个约束放在模型里才自然,放控制器里就是污染
MY_Model 基类怎么定义才真正通用?
关键不是堆方法,而是定规则。建议从这几点入手:
- 类名必须是
MY_Model,文件存为application/core/MY_Model.php,且确保$config['subclass_prefix'] = 'MY_';已在config.php中设置 - 构造函数里自动加载数据库:
$this->load->database();,避免每个子类重复写 - 定义
$table属性(如protected $table = 'users';),所有子类必须显式声明,不设默认值——表名不确定时强行通用反而危险 - 封装
create()而非insert():前者可自动注入created_at、过滤非表字段、检查必填项;后者只是裸 DB 调用 - 读取方法统一返回数组(
get())、单条记录(find($id))、或 FALSE(查无结果),不返回对象或 Query 对象,降低下游使用门槛
示例节选:
class MY_Model extends CI_Model
{
protected $table;
public function __construct()
{
parent::__construct();
$this->load->database();
}
public function create($data)
{
if (empty($this->table)) {
return FALSE;
}
// 自动加 created_at
$data['created_at'] = date('Y-m-d H:i:s');
return $this->db->insert($this->table, $data);
}
public function find($id)
{
return $this->db->where('id', $id)->get($this->table)->row_array();
}
}
子类继承时最容易踩的坑
封装后反而出错,往往是因为忽略了上下文差异:
-
$this->db->insert_id()在批量插入或事务中不可靠,create()方法若需返回 ID,必须紧跟insert()后立刻调用,不能延迟 -
update()封装时必须强制要求传where条件,否则可能全表更新——别信 “默认按 id 更新” 这种假设,find($id)返回 NULL 时,update(NULL, $data)会炸 - 软删除字段(如
deleted_at)不能只在delete()方法里处理,get()和find()也得默认加where('deleted_at IS NULL'),否则逻辑不自洽 - 字段白名单控制(
$allowed_fields = ['name', 'email'])必须在每个写操作里做,不能只靠数据库层约束——用户提交的is_admin=1若没过滤,直接进库就是提权漏洞
create(),而是让所有子模型在字段校验、时间处理、软删除、事务边界上行为一致。一旦某处绕过基类直连 $this->db,整套封装就形同虚设。











