如何只应用全部验证约束的一个子集(验证组)

3.4 版本
维护中的版本

默认情况下,当验证一个对象时,这个类的所有约束都将被检查,来检查它们是否真的能通过。一些情况下,你只需要使用该类的其中某些规则来验证一个对象。要做到这些,你可以组织每一个约束到一个或者多个验证组中,然后应用使用其中一组验证。

比如,假设你有一个User类,它会在用户注册和用户更新他们的联系信息时使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// src/AppBundle/Entity/User.php
namespace AppBundle\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;
}
1
2
3
4
5
6
7
8
9
10
11
# src/AppBundle/Resources/config/validation.yml
AppBundle\Entity\User:
    properties:
        email:
            - Email: { groups: [registration] }
        password:
            - NotBlank: { groups: [registration] }
            - Length: { min: 7, groups: [registration] }
        city:
            - Length:
                min: 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!-- src/AppBundle/Resources/config/validation.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://symfony.com/schema/dic/constraint-mapping
        http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd
    ">
 
    <class name="AppBundle\Entity\User">
        <property name="email">
            <constraint name="Email">
                <option name="groups">
                    <value>registration</value>
                </option>
            </constraint>
        </property>
 
        <property name="password">
            <constraint name="NotBlank">
                <option name="groups">
                    <value>registration</value>
                </option>
            </constraint>
            <constraint name="Length">
                <option name="min">7</option>
                <option name="groups">
                    <value>registration</value>
                </option>
            </constraint>
        </property>
 
        <property name="city">
            <constraint name="Length">
                <option name="min">7</option>
            </constraint>
        </property>
    </class>
</constraint-mapping>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
 
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints as Assert;
 
class User
{
    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint('email', new Assert\Email(array(
            'groups' => array('registration'),
        )));
 
        $metadata->addPropertyConstraint('password', new Assert\NotBlank(array(
            'groups' => array('registration'),
        )));
        $metadata->addPropertyConstraint('password', new Assert\Length(array(
            'min'    => 7,
            'groups' => array('registration'),
        )));
 
        $metadata->addPropertyConstraint('city', new Assert\Length(array(
            "min" => 3,
        )));
    }
}

在这个配置中,有三个验证组:

Default

包含当前类的约束和所有没有分配到任何组的约束规则

User

等于在Default组中的User对象所有的约束。他总是以类的名称命名。它和default组的不同如下所示。

registration

只包含了emailpassword字段的校验规则

Default组中的约束是一个没有明确组配置的类的约束,或者是被配置为一组等于类名Default字符串的约束。

当只是用户对象验证的时候,没有Default组和User组的差别。但是,如果User嵌入了对象就有区别了。例如,User有一个address属性,它包含很多的Address对象,并且你要添加有效的约束到这个属性,所以当你验证User对象时,你就要对他进行验证。

如果你验证User使用Default组,Address类将使用Default组约束。但是,如果你验证的User使用这个User验证组,那么address类将被User组验证。

换句话说,在default组和类名组(例如User)是一样的,除了在类被嵌入到另一个对象时,会根据另一个类的约束验证。

如果你有继承(如,User extends BaseUser)并且你去验证子类的类名(如User),那么所有UserBaseUser的约束都将被验证。但是,如果你验证使用基类(如BaseUser),那么只有默认约束和BaseUser类被验证;

告诉validator使用指定的验证组,传一个或者多个组名作为validate()方法的第三个参数即可:

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

如果你没有指定组,所有的约束都属于Default.

当然,你通常是间接验证表单库,如何在表单使用验证组请看 验证分组.

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)