简体   繁体   English

在Symfony 4中验证Rest Api

[英]Validation for Rest Api in Symfony 4

I'm going to write REST API for my project. 我将为我的项目编写REST API。 I'm using symfony 4. I saw several examples, but non of them fit me. 我正在使用symfony4。我看到了几个示例,但没有一个适合我。

  1. Validation with Form object. 使用Form对象进行验证。 It doesn't work for me, because it's API, there are no forms. 它对我不起作用,因为它是API,没有表单。 I don't want to write dummy classes just to support this functionality. 我不想编写哑类只是为了支持此功能。
  2. On this page https://symfony.com/doc/current/validation.html they suggest 4 ways: Annotation, yml, xml, php. 在此页面https://symfony.com/doc/current/validation.html上,他们建议了4种方式:注释,yml,xml,php。 This solution doesn't fit me because this validation is related to the entity, API - is much mode wider: it has limit, offset, filters and other fields, that doesn't belong to an entity. 此解决方案不适合我,因为此验证与实体API有关-模式更广泛:它具有限制,偏移量,过滤器和其他不属于实体的字段。

So, I think I need to write validator which has an array of constraints for all possible fields. 因此,我想我需要编写验证器,该验证器对所有可能的字段都有一系列约束。 I just don't know what is the best way to present this. 我只是不知道什么是最好的呈现方式。 Have you ever seen something similar? 你见过类似的东西吗?

PS Before writing this post I used stackoverflow search. PS在写这篇文章之前,我使用了stackoverflow搜索。 I didn't find useful answers. 我没有找到有用的答案。

Looking at your example ( example.com/api/categories?limit=20&offset=300&filter=something ) I guess your action would look something like this: 查看您的示例( example.com/api/categories?limit=20&offset=300&filter=something ),我想您的操作将如下所示:

public function getCategories(?int $limit, ?int $offset, ?string $filter)
{
    //...
}

Collection validation 馆藏验证

You can define your constraints as an array (and later abstract it away into its own class), and pass it as the second argument to your validator. 您可以将约束定义为数组(然后将其抽象为自己的类),并将其作为第二个参数传递给验证程序。

$constraint = new Assert\Collection([
    'limit' => [
        new Assert\Range(['min' => 0, 'max' => 999]),
        new Assert\DivisibleBy(0.5)
    ],
    'offset' => new Assert\Range(['min' => 0, 'max' => 999]),
    'filter' => new Assert\Regex("/^\w+/")
]);

$validationResult = $this->validator->validate(
    ['limit' => $limit, 'offset' => $offset, 'filter' => $filter],
    $constraint
);

Documentation link . 文档链接

Validate one by one 一一验证

Pass the constraint to the validator as second argument, for every parameter you want to validate. 对于要验证的每个参数,将约束作为第二个参数传递给验证器。

$offsetValidationResult = $this->validator->validate(
    $offset,
    new Assert\Range(['min' => 0, 'max' => 999])
);
//...

Documentation link . 文档链接

Object validation 对象验证

Create a class with the 3 fields in it. 创建一个包含3个字段的类。

class FilterParameters
{
    public function __construct($limit, $offset, $filter)
    {
        $this->limit = $limit;
        $this->offset = $offset;
        $this->filter = $filter;
    }

    // No getters/setters for brevity
    /**
     * @Assert\DivisibleBy(0.25)
     */
    public $limit;
    /**
     * @Assert\Range(min = 0, max = 999)
     */
    public $offset;
    /**
     * @Assert\Regex("/^\w+/")
     */
    public $filter;
}

Instantiate and validate it. 实例化并验证它。

$validationResult = $this->validator->validate(
    new FilterParameters($limit, $offset, $filter)
);

Documentation link . 文档链接

I think to use forms as usual is the very clean and nice. 我认为照常使用表格是非常干净和不错的。 https://codereviewvideos.com/course/beginners-guide-back-end-json-api-front-end-2018/video/validating-json-data-symfony https://codereviewvideos.com/course/beginners-guide-back-end-json-api-front-end-2018/video/validating-json-data-symfony

I choose this api, because it was the fastest in my tests. 我选择此api,因为它是我测试中最快的。 You do not have to buy the course (but you might if you like the code), just follow the "raw symfony 4" articles in this series (you also dont need the behat part) 您不必购买该课程(但是,如果您喜欢此代码,则可以这样做),只需遵循本系列中的“ raw symfony 4”文章(您也不需要behat部分)

"Limit", "offset" and "filter" functionality belongs to your repositories. “限制”,“偏移”和“过滤器”功能属于您的存储库。 Same way as you pass the id here to the repository 与您将ID传递到存储库的方式相同

/**
 * Class AlbumController
 * @package App\Controller
 */
class AlbumController extends AbstractController
{
    // ....

    /**
     * @Route(
     *     path         = "/api/album/{id}",
     *     name         = "get_album",
     *     methods      = {"GET"},
     *     requirements = {"id"="\d+"}
     * )
     * @param int $id
     *
     * @return JsonResponse
     */
    public function get($id)
    {
        return new JsonResponse($this->findAlbumById($id), JsonResponse::HTTP_OK);
    }  

    /**
     * @param $id
     *
     * @return Album|null
     * @throws NotFoundHttpException
     */
    private function findAlbumById($id)
    {
        $album = $this->albumRepository->find($id);

        if ($album === null) {
            throw new NotFoundHttpException();
        }

        return $album;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM