CI4实体类非必须但绕不开手动映射,需继承CodeIgniter\Entity并配置$returnType才能启用;$datamap仅影响属性读写不作用于查询条件,setter/getter需显式调用且命名规范。

CI4 实体类不是“必须写”,但不写就绕不开手动映射
CI4 的实体类(Entity)本质是数据容器 + 属性访问封装,它不参与数据库操作本身,也不自动校验或持久化。你完全可以用数组或 stdClass 传值,但一旦涉及字段过滤、类型转换、隐藏敏感属性或统一格式化(比如把 created_at 转成 Carbon 实例),实体类就变成刚需。
常见错误现象:控制器里直接 $user = $this->userModel->find(1); 拿到数组,后续想调用 $user->getCreatedAt()->toDateString() 报错——因为数组没有方法;或者修改了 $user['password'] 后调用 save(),结果密码明文入库——因为没走实体的 setter 过滤逻辑。
- 实体类必须继承
CodeIgniter\Entity,且字段名需与数据库列名一致(或通过$datamap映射) - 定义
$dates数组可让指定字段自动转为DateTime实例(如['created_at', 'updated_at']) -
$casts支持'status' => 'int'、'meta' => 'json'等类型强制转换,避免手动(int)或json_decode() - 敏感字段(如
password_hash)应加入$hidden,防止toArray()或 JSON 输出时泄露
模型必须显式关联实体,否则 find() / findAll() 返回纯数组
CI4 默认关闭实体返回,哪怕你已写好 UserEntity,模型的 find() 仍只返回关联数组。这是新手最常忽略的配置点。
在模型类中必须设置:protected $returnType = \App\Entities\User::class;。漏掉这行,所有查询结果都是数组,实体里的 getFoo()、setBar() 全部失效。
- 若实体类不在默认命名空间(
App\Entities),要写完整命名空间路径 -
$useSoftDeletes = true时,实体不会自动过滤软删除字段,得靠$this->withDeleted()或$this->withoutDeleted()控制 - 批量操作如
insertBatch()不走实体逻辑,只认数组;要用实体批量插入,得先用new UserEntity($data)构造再逐个insert()
实体字段映射:数据库列名 ≠ 实体属性名,但别滥用 $datamap
当数据库字段是 user_name,而你想在实体里用 $user->name 访问,就得靠 $datamap = ['name' => 'user_name'];。但它不是万能别名层——所有数据库写入、查询条件、验证规则依然以真实列名为准。
典型坑:设了 $datamap = ['id' => 'user_id'],然后在控制器里写 $model->where('id', 123)->first(),结果查不到——因为 where() 不解析 $datamap,实际执行的是 WHERE id = 123,而表里根本没有 id 字段。
-
$datamap只影响实体属性读写,不影响 Query Builder 的字段识别 - 如果数据库列名含前缀(如
tbl_users.user_name),$datamap值必须是去掉表名的纯列名(即'user_name') - 想统一处理前缀字段,建议用视图或数据库别名,而不是靠实体硬映射
实体生命周期里最容易被跳过的一步:setter 方法要主动触发
CI4 实体不会像 Laravel 那样在赋值时自动调用 setPasswordAttribute()。你得显式调用 $user->password = 'raw'; 或 $user->setPassword('raw');,才能触发自定义 setter 里的哈希逻辑。
常见错误:直接 $user->password = password_hash($raw, PASSWORD_DEFAULT);,结果下次调用 $user->password 时又走 getter,可能重复哈希或返回 null。
- setter 方法名必须是
setXxx(),对应属性xxx(首字母小写),且参数名必须为$value - getter 同理,
getXxx()返回处理后的值,但不会修改原始存储字段,除非你在里面显式改$this->attributes['xxx'] - 实体构造时传入的数组,会自动触发对应 setter(如果存在),但仅限于键名匹配的字段


















