【发布时间】:2019-08-01 21:51:27
【问题描述】:
我正在使用 JSON:API 规范在 Laravel 中实现一个 API。
在其中我有一个资源,我们称之为 Ponds,与另一个资源具有多对多关系,我们称之为 Ducks。
根据 JSON:API 规范,为了删除这种关系,我应该使用 DELETE /ponds/{id}/relationships/ducks 端点,并请求以下正文:
{
"data": [
{ "type": "ducks", "id": "123" },
{ "type": "ducks", "id": "987" }
]
}
这是由 PondRemoveDucksRequest 处理的,如下所示:
<?php
...
class PondRemoveDucksRequest extends FormRequest
{
public function authorize()
{
return $this->allDucksAreRemovableByUser();
}
public function rules()
{
return [
"data.*.type" => "required|in:ducks",
"data.*.id" => "required|string|min:1"
];
}
protected function allDucksAreRemovableByUser(): bool
{
// Here goes the somewhat complex logic determining if the user is authorized
// to remove each and every relationship passed in the data array.
}
}
问题是,如果我发送一个正文,例如:
{
"data": [
{ "type": "ducks", "id": "123" },
{ "type": "ducks" }
]
}
,我得到一个 500,因为首先触发了授权检查,并且它依赖于数组中每个项目中存在的 id。理想情况下,我希望收到来自规则验证的标准消息的 422 错误。
我看到的快速解决方法是在 allDucksAreRemovableByUser() 方法中添加 id 存在检查,但这似乎有点 hacky。
有没有更好的方法先检查验证规则,然后才进行授权部分?
提前致谢!
【问题讨论】:
-
请问您可以在哪里发布您调用验证规则的位置吗?
-
@party-ring 我不确定我是否得到你的问题。据我了解,在控制器方法的参数中使用请求时会自动检查验证规则。
-
在您的控制器中,当您检索请求时,您能否 dd
$request->validated();只是为了查看请求是否通过验证?因为如果它通过了,那么验证就有问题,如果它失败了,那么你需要拒绝那个请求:) -
@party-ring 规则验证本身似乎有效,因为如果在已删除的项目之一中提供了错误的“类型”,它会返回 422。我会检查是否添加了 $request->validated();不过,有助于规则顺序与授权检查,谢谢!
-
@party-ring 在控制器中添加
$request->validated()调用没有任何区别。我假设 FormRequest 的授权逻辑在控制器方法中的任何代码之前执行。有帮助的是在authorize()方法的开头添加$this->getValidatorInstance()->validated();。getValidatorInstance()是必需的,因为在执行授权逻辑时,验证器尚未实例化。这样我就得到了基于rules()的标准错误消息和验证。不过看起来还是有点乱,我正在考虑将其移至中间件。