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
相关产品推荐
相关产品推荐

