一文带你了解 Laravel 中的 Mass-Assignment (批量赋值)
Laravel Eloquent ORM 提供了简单的 API 与数据库进行交互。它是通过 [Active Record] (https://www.martinfowler.com/eaaCatalog/ac...) 模式来实现的。数据库中的每个表都映射为一个 Model class 文件,并通过该文件与数据库的表进行交互。
批量赋值
现在让我们来分解这个词组。
- 批量 :意味着字段数量比较多
- 赋值 :需把前端提交的值赋值给指定的变量
为了使开发人员更方便,Eloquent ORM 提供了批量赋值功能,该功能可以帮助开发者将大量数值插入(更新)到数据库中。
没有批量赋值时 😩
让我们想象一下,一个包含 10 个用户信息的表单。
<form method="POST" action="/signup">
<input type="text" name="name" />
<input type="text" name="user_name" />
<input type="text" name="password" />
<input type="text" name="address" />
<input type="text" name="city" />
...
...
...
<button type="submit">Signup</button>
</form>
Controller's store 方法内容如下:
public function store(Request $request)
{
// 执行验证
$user = new User;
$user->name = $request->get('name');
$user->user_name = $request->get('user_name');
$user->password = bcrypt($request->get('password'));
$user->address = $request->get('address');
$user->city = $request->get('city');
//....
$user->save();
}
我们需要将用户信息分别获取并赋值给 Model,然后保存到数据库中。
有没有一种方法,不需要单独获取数据的方式,而是通过批量获取数据呢?
使用批量赋值时 🥳
Laravel Eloquent ORM 提供了 create 方法,它可以帮助你使用一行代码来保存所有的用户信息。
public function store(Request $request)
{
// 执行验证
$user = User::create($request->all());
}
是不是酷酷的 🤓 只用一行代码就可以将用户信息都保存到数据库中。将来,如果我们在 HTML 代码中添加了更多的用户信息,也无需担心被遗漏而不能保存到数据库中。
输入字段 name 属性必须是数据库表中的字段名.
潜在漏洞
为了方便理解,数据库中的 users 表有 is_admin 字段,字段保存的值只能是 true 或 false 。
恶意的用户可以伪造 HTML,通过设置隐藏值,将 is_admin 字段设置为true:
<form method="POST" action="/signup">
<input type="hidden" name="is_admin" value="1" />
<input type="text" name="name" />
<input type="text" name="user_name" />
<input type="text" name="password" />
<input type="text" name="address" />
<input type="text" name="city" />
...
...
...
<button type="submit">Signup</button>
</form>
因为我们使用了批量赋值,所以用户的 is_admin 字段被设置为 true 了,而且该用户还拥有了管理员权限,糟糕,这当然不是我们想要的。 😡
避免漏洞
有两种方法可以处理此问题。
第一种:我们可以指定(白名单)哪些字段可以被批量赋值
Laravel Eloquent 提供了一种简单的方法来实现这一点。在您的模型类中,添加 $fillable
属性,并指定数组中列的名称,如下所示:
class User extends Model
{
protected $fillable = [
'name',
'user_name',
'password',
'address',
'city'
...
];
}
除了以上字段的其他字段只要传参给 create() 方法就会抛出 MassAssignmentException 异常。
第二种、我们可以指定(黑名单)哪些列不能批量赋值。
您可以通过在模型类中添加$guarded
属性来实现这一点:
class User extends Model
{
protected $guarded = ['is_admin'];
}
除了 is_admin
之外的所有字段现在都可以进行批量赋值。
需要注意的是,
$fillable
和$guarded
你只能二选一。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。