Как применить только подмножество всех ваших ограничений валидации (группы валидации)

Дата обновления перевода 2023-01-09

Как применить только подмножество всех ваших ограничений валидации (группы валидации)

По умолчанию, при валидации объекта, все ограничения этого класса будут проверены на предмет того, действительно ли они подойдут. Однако, в некоторых случаях, вам понадобится валидировать объект только по отношению к некоторым ограничениям этого класса. Чтобы сделать это, вы можете организовать каждое ограничение в одну или более "групп валидации", а потом применить валидацию только к одной группе ограничений.

Например, представьте, что у вас есть класс User, который используется как при регистрации пользователя, так и при обновлении контактной информации позже:

  • Attributes
  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/Entity/User.php
namespace App\Entity;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;

class User implements UserInterface
{
    #[Assert\Email(groups: ['registration'])]
    private $email;

    #[Assert\NotBlank(groups: ['registration'])]
    #[Assert\Length(min: 7, groups: ['registration'])]
    private $password;

    #[Assert\Length(min: 2)]
    private $city;
}

В такой конфигурации существует три группы валидации:

Default
Содержит ограничения в текущем классе и все упомянутые классы, которые не принадлежат ни к одной другой группе. В этом примере, она содержит только поле city.
User
Эквивалентна всем ограничениям объекта User в группе Default. Это всегда является именем класса. Разица между этой группой и Default объясняется в Как применять группы валидации последовательно.
registration
Это пользовательская группа валидации, поэтому она содержит только ограничения, четко ассоциированные с ней. В этом пимере - только поля email и password.

Ограничения в группе класса Default - это ограничения, которые либо не имеют явной сконфигурированной группы, или которые сконфигурированы в группу, равную имени класса или строке Default.

Caution

При валидации только объекта пользователя (User), не существует разницы между группами Default и User. Но разница существует, если User имеет встроенные объекты. Например, представьте, что User имеет свойство address, которое содержит некоторый объект Address, и что вы добавили ограничение Valid к этому свойству, чтобы оно было валидировано при валидации объекта User.

Если вы валидируете User. используя группу Default, то любые ограничения в классе Address, которые находятся в группе Default будут использованы. Но, если вы валидируете User, используя группу валидации User, тогда будут валидированы только ограничения класса Address.

Другими словами, группа Default и группа класса имени (например, User) идентичны, кроме случаев, когда класс встрое в другой объект, чем тот, валидация которого проводится.

Если у вас есть наследование (например, User extends BaseUser) и вы валидируете с классом имени подкласса (т.е. User), то все ограничения в User и BaseUser будут валидированы. Однако, если вы валидируете, используя базовый класс (т.е. BaseUser), то будут валидированы только ограничения по умолчанию в классе BaseUser.

Чтобы сообщить валидатору об использовании конкретной группы, передайте одно или более имён групп в качестве третьего аргумента метода validate():

1
$errors = $validator->validate($author, null, array('registration'));

Если не указана ни одна группа, будут применены все ограничения, принадлежащие группе Default

Конечно же, вы чаще будете работать с валидацией не напрямую, а через библиотеку форм. Для информации о том, как использовать группы валидации внутри форм, смотрите Как определить, какие группы валидации использовать.