В Symfony есть встроенные валидаторы данных. Окей, а вы уверены что они работают и валидируют по всем правилам? Столкнулся с ситуацией, в которой валидароты скипали правила описанные в аннотациях объектов. Давайте покажу на примере. Допустим есть класс с пропертями, геттерами и сеттерами, т.е. типичный Data Transfer Object (DTO).
// src/Entity/Author.php
namespace App\Entity;
class Author
{
public $name;
}
А теперь навесим на него немного правил валидации (constraints):
// src/Entity/Author.php
// ...
use Symfony\Component\Validator\Constraints as Assert;
class Author
{
/**
* @Assert\NotBlank()
*/
public $name;
}
Теперь давайте немного повалидируем:
// ...
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use App\Entity\Author;
// ...
public function author(ValidatorInterface $validator)
{
$author = new Author();
// ... do something to the $author object
$errors = $validator->validate($author);
if (count($errors) > 0) {
/*
* Uses a __toString method on the $errors variable which is a
* ConstraintViolationList object. This gives us a nice string
* for debugging.
*/
$errorsString = (string) $errors;
return new Response($errorsString);
}
return new Response('The author is valid! Yes!');
}
Как думаете, провалидирует ли Symfony поля объекта? Всё зависит от того, как сконфигурирован валидатор и читает ли он мета-данные объектов. Если используется дефолтный фабричный метод:
Validation::createValidator();
То мне придётся вас огорчить, значения объектов валидироваться не будут! Это произойдёт потому, что валидатор создаётся без маппера аннотаций. Смотрим код vendor\symfony\symfony\src\Symfony\Component\Validator\Validation.php
/**
* Entry point for the Validator component.
*
* @author Bernhard Schussek <[email protected]>
*/
final class Validation
{
/**
* Creates a new validator.
*
* If you want to configure the validator, use
* {@link createValidatorBuilder()} instead.
*
* @return ValidatorInterface The new validator
*/
public static function createValidator()
{
return self::createValidatorBuilder()->getValidator();
}
/**
* Creates a configurable builder for validator objects.
*
* @return ValidatorBuilderInterface The new builder
*/
public static function createValidatorBuilder()
{
return new ValidatorBuilder();
}
}
Создать переконфигурированный валидатор можно так:
$validator = (new ValidatorBuilder())->enableAnnotationMapping()->getValidator();
И теперь можно вызывать валидацию объекта, только ни в коем случае нельзя передавать дополнительный параметр с массивом констрейтов, иначе валидатор возьмёт их, а не будет проверять по аннтоациям!
Ссылки для подробного изучения:
- https://symfony.com/doc/current/validation.html
- https://symfony.com/doc/3.4/components/validator/resources.html
- https://symfony.com/doc/3.4/components/validator/metadata.html