我正在寻找在Laravel表单请求中强制执行唯一字段的最佳方法,但编辑时除外。最明显的例子是只允许使用一次电子邮件地址,即系统中的每个用户都需要一个唯一的电子邮件地址。
通过使字段唯一来实现使用表单请求是直截了当的:
public function rules()
{
return [
'email' => ['required', 'email', 'unique:users,email'],
];
}
这使得该字段成为必需字段,验证为电子邮件并使其在用户表中唯一。非常适合创建新用户。但编辑怎么样?用户想要编辑他们的个人资料并再次保存相同的电子邮件地址(这是完全有效的)是完全合理的。但是,当然,unique
规则会触发,因为电子邮件已经“正在使用”(尽管用户试图自行编辑)。
Laravel提供了解决此问题的方法,方法是将user
表的ID传递给忽略:
'email' => ['required', 'email', 'unique:users,email,'.$userId]
但是如何获取用户ID?也许这是一个糟糕的例子,因为获取登录的用户ID是微不足道的,但是那些未存储在会话中的其他对象呢?
如果一个人正在使用REST,那么该对象的ID将在URL中并使用该路径提供:
$userId = $this->route('order');
但这看起来很脏。那么你没有使用REST修改对象的其他实例呢?在Laravel 5中编辑对象时,你们如何在表单请求中强制执行唯一性?
答案 0 :(得分:1)
如果需要,您可以拥有2个不同规则的表单请求。我不认为从FormRequest中提取信息以调整规则是脏的,因为FormRequest是一个请求,您可能需要一些信息来决定如何进行验证或授权。
我有一篇关于使用FormRequest进行创建和更新的帖子,使用规则中的唯一规则,该规则使用路由参数附加到唯一规则。 asklagbox - blog - Form Request for Store and Update
因为它使用HTTP方法来知道它是用于存储还是更新,如果是更新发生,则附加到唯一规则(Rest)。如果您没有使用REST,您仍然可以执行此操作,您只需要检查除HTTP方法之外的内容,以了解这是用于存储还是更新。您可以调整此方法以检查输入值而不是路由参数,以便在需要时附加到唯一规则。由于FormRequest非常特定于资源,因此您不必疯狂并想到每种可能的其他方式,或者您的app / API可能开始变得不一致。
// added to base FormRequest
protected $updateMethods = ['PUT', 'PATCH'];
protected function appendUnique($key, $keyName = 'id')
{
if (in_array($this->method(), $this->updateMethods) && $param = $this->route($key)) {
if ($param instanceof Model) {
$rt = "{$param->getKey()},{$param->getKeyName()}";
} else {
$rt = "{$param},{$keyName}";
}
return ','. $rt;
}
}
然后FormRequest的rules方法中的数组将具有以下内容:
'email' => 'required|unique:users,email'. $this->appendUnique('user'),
我经常使用Route Model Bindings(隐式和显式),这就是为什么这样设置的原因很少会让我检查的资源通过输入而不是路由参数传递。
我希望这会有所帮助。