В некоторых приложениях часто используется один и тот же набор ограничений в нескольких местах. Рассмотрим, например, приложение, которое позволяет регистрировать пользователей, изменять пароли, запоминать забытые пароли и т. д. Это приложение может использовать разные DTO для каждой функции, но все они содержат новый пароль пользователя, который должен проверяться одинаково во всех случаях.
В Symfony 5.1 вы можете быстро создать валидатор, использующий другие ограничения, независимо от того, встроены они или сделаны на заказ, благодаря новому ограничению Compound
:
namespace App\Validator;
use Symfony\Component\Validator\Constraints\Compound;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotCompromisedPassword;
use Symfony\Component\Validator\Constraints\Type;
/**
* @Annotation
*/
class MatchesPasswordRequirements extends Compound
{
protected function getConstraints(array $options): array
{
return [
new NotBlank(),
new Type('string'),
new Length(['min' => 12]),
new NotCompromisedPassword(),
];
}
}
Теперь вы можете применить это ограничение к вашим объектам как обычно:
namespace App\Dto;
// ...
use App\Validator\MatchesPasswordRequirements;
class ChangePasswordDto
{
/**
* @MatchesPasswordRequirements
*/
private $newPassword;
// ...
}
Проверять ограничения последовательно
В Symfony 5.1 также добавили другую, но связанную, функцию для последовательной проверки набора ограничений. Это было уже возможно благодаря ограничению GroupSequence, но в Symfony 5.1 упростили эту функцию с введением нового ограничения Sequential
.
Аргумент ограничения Sequentially
представляет собой набор из одного или нескольких ограничений. Symfony будет применять их в том же порядке, и в случае сбоя любого из них он остановится, а остальные ограничения не будут проверены. Это полезно для предотвращения как непредвиденных исключений типов, вызванных некоторыми ограничениями, так и ненужных вызовов медленных ограничений:
/**
* @var string
*
* @Assert\Sequentially({
* @Assert\Type("string"),
* @Assert\Length(min="4"),
* @Assert\Regex("[a-z]"),
* @SomeCustomConstraintWithHeavyExternalCalls(),
* })
*/
public $someProperty;