Laravel 6 – Model的mass assignment

Laravel 6 – Model的mass assignment

在Laravel的Eloquent ORM中,Mass Assignment是指以数组形式对模型的属性进行赋值,比如: Model->fill(array $attributes)Model::create(array $attributes) 。与之对立的是指单一属性的赋值,比如: Model->age=18

考虑这么一个场景:

在用户注册的时候,后台通常使用 User::create($attributes) 来进行用户模型的创建并写入数据库。这里的$attributes数组来自于用户提交的表单中的$_POST[’email’],  $_POST[‘password’]等属性。正常情况下用户注册时候只会提交表单中列出的属性,所以一切正常。

但是如果有个不怀好意的用户,在提交表单时候添加一些虚假数据进来,比如$_POST[‘user_type’]=’admin’。而偏巧数据库中user表结构就有一个字段’user_type’用来表示用户类型是管理员(admin)还是客户(customer)。那么此时他就成功注册了一个管理员用户。这不是我们想见到的。

为了防止这种情况的发送,Laravel提供了mass assignment保护。在定义一个Model类型的时候,必须通过 Model->fillable 或者 Model->guarded 变量来指定哪些属性是允许mass assignment的。(这两个成员变量继承自 trait GuardsAttributes ,默认情况下所有的属性都不允许mass  assignment。)

  • $fillable 数组的作用相当于一个白名单,在数组里的属性都是允许mass assignment的,不在里面的都是不允许的。
  • $guarded 数组的作用相当于黑名单,在数组里的属性都是不允许mass assignment的,不在里面的都是允许的。
  • 注意,在一个模型类的定义里, $fillable$guarded 只需要二选一即可,不要两个都出现。

在执行mass assignment方法的时候,Model会自动忽略不允许mass assignment的属性。详细实现可以查看 Model->fill(array $attributes) 的源码,实际上 Model::create() 底层也是调用了 Model->fill() 对新建实例的$attributes进行填充。mass assignment保护会在底层默默执行而不会报告异常,除非在所有属性都不允许mass assignment的情况下调用mass assignment方法时才会抛出一个MassAssignmentException异常。

以larael/ui自带的用户模型为例:

另外,Model还实现了 forceFill(array $attributes) 方法避开mass assignment保护。

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注