$fillable 必须显式声明,空数组或未定义即禁止批量赋值;Laravel 8 默认不放行任何字段,未设 $fillable 时 create()/fill() 会静默丢弃数据;仅允许前端传入且业务必需的字段(如 name、email)进入 $fillable,id、时间戳、敏感字段(is_admin、balance)及自动计算字段(如 slug)均不应列入;$fillable 与 $guarded 不能共存,推荐始终使用 $fillable;update()、updateOrCreate()、upsert() 均受 $fillable 约束,真正绕过需手动赋值+save();子类不继承父类 $fillable,须在每个具体模型中重新声明。

$fillable 必须显式声明,空数组或未定义等于完全禁止批量赋值。Laravel 8 默认不放行任何字段,不设 $fillable 就连 name、email 这类常规字段调用 create() 或 fill() 都会静默丢弃——不是报错,是“看起来成功但数据库没变”。
哪些字段该放进 $fillable
只放你**明确允许前端传入、且业务上必须由用户控制**的字段。比如注册表单里的 name、email、password;编辑资料时的 bio、avatar_url。其他一律排除。
-
id、created_at、updated_at、deleted_at不该进$fillable(时间戳由模型自动处理,id通常自增或 UUID 生成) -
is_admin、status、balance、user_id这类敏感字段,即使要写入,也应由服务端逻辑注入,而非依赖请求数据 - 如果字段需自动计算(如
slug来自title),它也不该在$fillable中——应通过模型事件或访问器处理
$fillable 和 $guarded 不能共存,选一个就到底
$fillable 是白名单,$guarded 是黑名单,Eloquent 要求二者二选一。一旦同时定义,$guarded 会被忽略,只认 $fillable;若 $fillable 为空数组 [],则所有字段都不允许批量赋值。
- 推荐始终用
$fillable:语义清晰、安全边界明确,新人不易误配 - 避免
protected $guarded = []:这等于开放全部字段,等同于关闭防护 - 不要写
protected $fillable = ['*']:Laravel 不支持通配符,会直接报错Call to undefined method ...::isFillable()
update() 方法绕过 $fillable?不,它也受控
很多人误以为 update() 不走 $fillable 检查——其实它**仍然校验**,只是校验发生在查询构造器层,而不是模型实例层。也就是说:User::where('id', 1)->update(['email' => 'x@y.z', 'is_admin' => true]) 中的 is_admin 若不在 $fillable 里,照样被过滤掉(前提是模型类已加载且 $fillable 生效)。
- 真正绕过
$fillable的只有手动赋值 +save():$user->is_admin = true; $user->save(); -
updateOrCreate()和upsert()同样受$fillable约束 - 如果你发现
update()写入了不该写的字段,大概率是模型没正确加载,或用了DB::table()直接操作,那当然不经过 Eloquent 校验
最容易被忽略的一点:$fillable 只对模型类本身生效,子类不会自动继承父类的 $fillable 设置。如果用了抽象基类或 trait 注入字段,必须在每个具体模型里重新声明 $fillable,否则那些字段就处于“不可批量赋值”状态。


















