Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validation for Rest Api in Symfony 4

I'm going to write REST API for my project. I'm using symfony 4. I saw several examples, but non of them fit me.

  1. Validation with Form object. It doesn't work for me, because it's API, there are no forms. 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. 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.

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?

P.S. Before writing this post I used stackoverflow search. I didn't find useful answers.

like image 939
Hevyweb Avatar asked Mar 04 '23 12:03

Hevyweb


1 Answers

Looking at your example (example.com/api/categories?limit=20&offset=300&filter=something) I guess your action would look something like this:

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.

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.

like image 200
mholle Avatar answered Mar 12 '23 09:03

mholle