CodeIgniter 4 中 Entity 类自动忽略未在 $fillable 显式声明或未被 $guarded 排除的字段;$fillable 与 $guarded 互斥,空数组启用严格保护,$guarded = ['*'] 无效,须用 $fillable = [] 实现全禁;数据库字段变更需同步更新 $fillable。

Entity类里哪些字段会被自动忽略填充
CodeIgniter 4 的 Entity 类默认启用“严格模式”:未显式声明为可填充($fillable)或未排除($guarded)时,fill()、setAttributes() 和模型的 insert()/update() 批量操作都会跳过所有属性,不报错但也不赋值。
-
$fillable = ['name', 'email']表示只允许这两个字段被批量填充,其余一律丢弃 -
$guarded = ['id', 'created_at']表示这两个字段禁止被填充,其余全部允许(等价于“白名单开放 + 黑名单拦截”) - 两者不能同时设置——如果同时存在,
$fillable优先级更高,$guarded被忽略 - 空数组
$fillable = []或$guarded = []都不是“全放开”,而是触发严格保护:无一字段可填充
为什么 $guarded = ['*'] 不起作用
$guarded = ['*'] 是常见误解,它不会通配屏蔽所有字段,而是字面意思——试图屏蔽一个叫 * 的字段(实际不存在),结果等于没设任何防护,所有字段都可被填充,相当于裸奔。
- 真正想“全部禁止填充”,必须用
$fillable = [] - 想“仅允许几个字段”,就老老实实列出来:
$fillable = ['title', 'slug', 'status'] - 调试时可用
var_dump($entity->getAttributes())看最终生效的属性,确认是否被意外过滤
数据库字段变更后 Entity 没同步导致填充失败
Entity 类不会自动读取数据库 Schema,$fillable 或 $guarded 写错、漏写新字段,就会在调用 $model->insert($data) 时静默丢弃数据——查数据库发现字段为空,但代码里明明传了值。
- 新增数据库字段后,必须同步更新 Entity 中的
$fillable数组 - 使用迁移脚本建表时,别依赖 Entity 自动推导;CI4 不支持像 Laravel 那样的
casts或自动 Schema 映射 - 临时调试可先注释掉
$fillable/$guarded,确认数据能进库后再补上限制 - 若用 IDE,给 Entity 加 PHPDoc 注解
@property string $name能辅助识别字段,但不影响运行时行为
和 Model 的 allowedFields 配置冲突吗
会。Model 层的 $allowedFields 和 Entity 的 $fillable / $guarded 是两套独立控制,且 Model 的校验发生在 Entity 之后——也就是说,即使 Entity 放行了某个字段,Model 还会再拦一次。
- 推荐只在 Entity 中统一管理填充规则,把
$allowedFields设为空数组[]或直接删掉该属性,避免双重过滤引发困惑 - 若保留
$allowedFields,它必须包含 Entity 中$fillable的全部字段,否则仍会被截断 - 执行
$model->insert($data)时,流程是:Entity::fill()→Model::insert()→Model::allowedFields检查 → 插入
allowedFields 是对传入数组做键过滤。两者叠加时,容易误以为“Entity 没生效”,其实是 Model 在后端又砍了一刀。

















