Laravel 授权前检查 FormRequest 的验证规则

Emi*_*mil 5 php laravel json-api

我正在使用 JSON:API 规范在 Laravel 中实现 API。

其中我有一个资源,我们称之为池塘,与另一个资源具有多对多关系,我们称之为鸭子。

根据 JSON:API 规范,为了删除这种关系,我应该使用 DELETE /ponds/{id}/relationships/ducks端点,并请求以下正文:

{
    "data": [
        { "type": "ducks", "id": "123" },
        { "type": "ducks", "id": "987" }
    ]
}
Run Code Online (Sandbox Code Playgroud)

这是由 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.
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,如果我发送如下正文:

{
    "data": [
        { "type": "ducks", "id": "123" },
        { "type": "ducks" }
    ]
}
Run Code Online (Sandbox Code Playgroud)

,我得到 500,因为授权检查首先被触发,并且它依赖于数组中每个项目中存在的 id。理想情况下,我希望收到 422 错误以及来自规则验证的标准消息。

我看到的快速修复方法是在 allDucksAreRemovableByUser() 方法中添加 id 存在检查,但这似乎有点 hacky。

有没有更好的方法先检查验证规则,然后再进行授权部分?

提前致谢!

Pet*_*erA 0

这是与您尝试的方法略有不同的方法,但它可能会为您实现所需的结果。

如果您尝试验证给定的鸭子 ID 是否属于该用户,可以在规则本身中完成此操作,如下所示:

"data.*.id" => "exists:ducks,id,user_id,".Auth::user()->id
Run Code Online (Sandbox Code Playgroud)

该规则询问ducks表中是否存在与id匹配的记录,其中user_id是当前登录的user_id。

如果您使用“bail”将其链接到现有规则(required|string|min:1),那么它不会运行查询,除非它首先通过了其他三个规则:

"data.*.id" => "bail|required|string|min:1|exists:ducks,id,user_id,".Auth::user()->id
Run Code Online (Sandbox Code Playgroud)