Задача: `use SymfonyComponentValidatorConstraintsLength; use SymfonyComponentValidatorConstraintsNotBlank; use SymfonyComponentValidatorConstraintsRegex;
class Request { #[NotBlank()] #[Length(min: 3, max: 10)] #[Regex(pattern: '/^[a-z]+$/')] #[Regex(pattern: '/^(value|foo)+$/', match: false)] public ?string $foo; } Замечаем, что часто пишем одно и то же в ассертах. Решение 1: https://symfony.com/doc/current/reference/constraints/Compound.html `use SymfonyComponentValidatorConstraintsCompound; use SymfonyComponentValidatorConstraints as Assert;
#[Attribute] class PasswordRequirements extends Compound { protected function getConstraints(array $options): array { return [ new AssertNotBlank(), new AssertType('string'), new AssertLength(min: 12), new AssertNotCompromisedPassword(), new AssertPasswordStrength(minScore: 4), ]; } } Compound позволяет собрать в один Constraint несколько валидаций. А теперь усложним немного задачу: обычными валидаторами наша задача не покрывается. Допустим, нужно сходить в бд/апи/к оракулу за данными, чтобы их отвалидировать.
Решение 2: https://symfony.com/doc/current/validation/custom_constraint.html#creating-the-constraint-class Пишем кастомный валидатор. Не находим в доке способ вызвать нативные валидаторы. Однако, в исходниках ExecutionContextInterface можно найти: `/**
- Returns the validator.
- Useful if you want to validate additional constraints:
- public function validate(mixed $value, Constraint $constraint): void
- {
- $validator = $this->context->getValidator();
- $violations = $validator->validate($value, new Length(min: 3));
- if (count($violations) > 0) {
- // ...
- }
- } */ public function getValidator(): ValidatorInterface; Таким образом, проверяем наше $value нативными валидаторами, а потом уже прикручиваем нашу сложную логику проверки.```