我正在使用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存在检查,但这似乎有些hacker。
是否有更好的方法先检查验证规则,然后再进行授权部分?
谢谢!
答案 0 :(得分:2)
1-在App \ Requests目录中创建名为“ FormRequest”的抽象类,并覆盖 validateResolved()方法:
<?php
namespace App\Http\Requests;
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Foundation\Http\FormRequest as BaseFormRequest;
abstract class FormRequest extends BaseFormRequest
{
/**
* Validate the class instance.
*
* @return void
* @throws AuthorizationException
* @throws ValidationException
*/
public function validateResolved()
{
$validator = $this->getValidatorInstance();
if ($validator->fails())
{
$this->failedValidation($validator);
}
if (!$this->passesAuthorization())
{
$this->failedAuthorization();
}
}
}
2-使用自定义FormRequest扩展您的FormRequests
<?php
namespace App\Http\Requests\Orders;
use App\Http\Requests\FormRequest;
class StoreOrderRequest extends FormRequest
{
}
答案 1 :(得分:0)
这里的方法与您尝试的方法略有不同,但是它可以为您实现所需的结果。
如果您要尝试验证给定的鸭子ID是否属于用户,可以在规则本身中完成以下操作:
"data.*.id" => "exists:ducks,id,user_id,".Auth::user()->id
此规则询问在ducks表中是否存在与id匹配的记录,以及user_id是当前登录的user_id的位置。
如果使用'bail'将其链接到现有规则(必需| string | min:1),则除非先通过了其他三个规则,否则它将不会运行查询:
"data.*.id" => "bail|required|string|min:1|exists:ducks,id,user_id,".Auth::user()->id
答案 2 :(得分:-1)
在$this->getValidatorInstance()->validate();
方法开始时添加authorize()