You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 9中protected $fillable未生效,未触发MassAssignmentException异常

问题分析与解决方案

首先明确Laravel批量赋值的核心规则:

  • 当模型定义了$fillable时,不在数组中的字段会被自动过滤,不会被写入数据库,也不会抛出MassAssignmentException异常。
  • 只有当模型**既没有定义$fillable也没有定义$guarded**时,尝试批量赋值才会触发该异常。

你遇到的"数据成功存入"可能是以下两种情况之一:

情况1:数据库默认值导致的误解

你的type字段设置了默认值1,Laravel实际上已经过滤了提交的type字段,但数据库自动用默认值填充了该字段,所以你看到数据库中有值,但这个值并非来自表单提交。

验证方法:

  • 在控制器中打印提交的数据和创建后的模型数据:
    $data = $request->all();
    $subject = Subject::create($data);
    dd($subject->type); // 若输出null,说明Laravel确实过滤了type字段,数据库值是存储层面的默认填充
    

情况2:批量赋值保护未生效

如果确实是表单提交的type值被写入了数据库,说明批量赋值保护没有生效,排查以下几点:

1. 检查模型Subject.php的代码

  • 确认没有设置$guarded = []:这个设置会允许所有字段批量赋值,完全忽略$fillable的配置。
  • 确认模型中没有调用$this->unguard()或static::unguard():该方法会临时或永久解除当前模型的批量赋值保护。

2. 检查全局配置

  • 查看App\Providers\AppServiceProvider.php的boot方法,是否存在Model::unguard()调用:这会全局禁用所有模型的批量赋值保护。
  • 对于Laravel 5.1及更早版本,检查config/app.php中的protect_against_mass_assignment是否为false,如果是改为true。

3. 确认字段名匹配

检查表单中的字段名是否和数据库字段名完全一致(比如是否大小写错误,如Type和type),Laravel的字段匹配是区分大小写的。

如何主动触发MassAssignmentException

如果你需要在传入未授权字段时强制抛出异常,可以在模型中添加以下逻辑:

protected static function booted()
{
    static::creating(function ($model) {
        $fillable = $model->getFillable();
        $input = request()->all();
        $unauthorizedFields = array_diff(array_keys($input), $fillable);
        if (!empty($unauthorizedFields)) {
            throw new \Illuminate\Database\Eloquent\MassAssignmentException(
                'Unauthorized fields: ' . implode(', ', $unauthorizedFields)
            );
        }
    });
}

内容的提问来源于stack exchange,提问作者Chunk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:33:21