如何按顺序应用验证组
在某些情况下,需要按照步骤验证你的组。要做到这一点,你可以使用GroupSequence
功能。在这种情况下,给一个对象定义一组顺序,也就是确定组验证的顺序。
例如,假设你有一个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
25
26
27
28
29
|
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @Assert\GroupSequence({"User", "Strict"})
*/
class User implements UserInterface
{
/**
* @Assert\NotBlank
*/
private $username;
/**
* @Assert\NotBlank
*/
private $password;
/**
* @Assert\IsTrue(message="The password cannot match your username", groups={"Strict"})
*/
public function isPasswordLegal()
{
return ($this->username !== $this->password);
}
} |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# src/AppBundle/Resources/config/validation.yml
AppBundle\Entity\User:
group_sequence:
- User
- Strict
getters:
passwordLegal:
- 'IsTrue':
message: 'The password cannot match your username'
groups: [Strict]
properties:
username:
- NotBlank: ~
password:
- NotBlank: ~ |
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
|
<!-- 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="username">
<constraint name="NotBlank" />
</property>
<property name="password">
<constraint name="NotBlank" />
</property>
<getter property="passwordLegal">
<constraint name="IsTrue">
<option name="message">The password cannot match your username</option>
<option name="groups">
<value>Strict</value>
</option>
</constraint>
</getter>
<group-sequence>
<value>User</value>
<value>Strict</value>
</group-sequence>
</class>
</constraint-mapping> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// 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('username', new Assert\NotBlank());
$metadata->addPropertyConstraint('password', new Assert\NotBlank());
$metadata->addGetterConstraint('passwordLegal', new Assert\IsTrue(array(
'message' => 'The password cannot match your first name',
'groups' => array('Strict'),
)));
$metadata->setGroupSequence(array('User', 'Strict'));
}
} |
在这个案例中,他会先验证所有验证中的User
组(就好像以前的Default
组一样)。只有当这组所有约束都通过时,才会进行第二组验证,strict
。
正如你已经从上节中看到的,default
组和类名组(如User
组)都是相同的。然而,使用组顺序时,他们不再相同了。Default
组将引用组序列,而不是所有不属于任何群体的约束。
这意味着,当你指定一组顺序,你必须要使用 {ClassName}
(例如User
)组。当你使用Default
,你会得到一个无线递归。(default
组引用组顺序,其中将包含default
,他会引用同组的组顺序,...组)。
约束组顺序提供器(Providers) ¶
想象一下一个User
实体可以是一个普通的用户也可以是一个高级用户。当他是一个高级用户,user实体应该添加一些额外的约束(例如 信用卡详细信息)。去动态的确认哪个组被激活,你需要创建一个验证组顺序提供器。首先,创建实体并给他一个新的约束组Premium
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
class User
{
/**
* @Assert\NotBlank()
*/
private $name;
/**
* @Assert\CardScheme(
* schemes={"VISA"},
* groups={"Premium"},
* )
*/
private $creditCard;
// ...
} |
|
# src/AppBundle/Resources/config/validation.yml
AppBundle\Entity\User:
properties:
name:
- NotBlank: ~
creditCard:
- CardScheme:
schemes: [VISA]
groups: [Premium] |
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
|
<!-- 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="name">
<constraint name="NotBlank" />
</property>
<property name="creditCard">
<constraint name="CardScheme">
<option name="schemes">
<value>VISA</value>
</option>
<option name="groups">
<value>Premium</value>
</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
|
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Mapping\ClassMetadata;
class User
{
private $name;
private $creditCard;
// ...
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint('name', new Assert\NotBlank());
$metadata->addPropertyConstraint('creditCard', new Assert\CardScheme(
'schemes' => array('VISA'),
'groups' => array('Premium'),
));
}
} |
现在,改写User
类并实现 GroupSequenceProviderInterface并且添加getGroupSequence()方法,他能以一个数组形式返回我们使用的组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
// ...
use Symfony\Component\Validator\GroupSequenceProviderInterface;
class User implements GroupSequenceProviderInterface
{
// ...
public function getGroupSequence()
{
$groups = array('User');
if ($this->isPremium()) {
$groups[] = 'Premium';
}
return $groups;
}
} |
最后,你必须告诉你的验证组件,你的User
类使用组顺序进行验证:
1
2
3
4
5
6
7
8
9
10
11
12
|
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
// ...
/**
* @Assert\GroupSequenceProvider
*/
class User implements GroupSequenceProviderInterface
{
// ...
} |
|
# src/AppBundle/Resources/config/validation.yml
AppBundle\Entity\User:
group_sequence_provider: true |
1
2
3
4
5
6
7
8
9
10
11
12
|
<!-- 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">
<group-sequence-provider />
<!-- ... -->
</class>
</constraint-mapping> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// src/AppBundle/Entity/User.php
namespace AppBundle\Entity;
// ...
use Symfony\Component\Validator\Mapping\ClassMetadata;
class User implements GroupSequenceProviderInterface
{
// ...
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->setGroupSequenceProvider(true);
// ...
}
} |