【发布时间】:2014-02-22 07:20:00
【问题描述】:
在我的 Symfony 2 (2.4.2) 应用程序中,有一个由 3 个字段组成的表单类型。
我希望验证是这样的:如果 field A 和 field B 为空白,field C 不应为空白。这意味着至少一个字段应该接收一些数据。
目前,我在控制器中检查接收到的数据。有更推荐的方法吗?
【问题讨论】:
在我的 Symfony 2 (2.4.2) 应用程序中,有一个由 3 个字段组成的表单类型。
我希望验证是这样的:如果 field A 和 field B 为空白,field C 不应为空白。这意味着至少一个字段应该接收一些数据。
目前,我在控制器中检查接收到的数据。有更推荐的方法吗?
【问题讨论】:
还有比编写自定义验证器更简单的解决方案。最简单的可能是表达式约束:
class MyEntity
{
private $fieldA;
private $fieldB;
/**
* @Assert\Expression(
* expression="this.fieldA != '' || this.fieldB != '' || value != ''",
* message="Either field A or field B or field C must be set"
* )
*/
private $fieldC;
}
您还可以向您的类添加验证方法并使用回调约束对其进行注释:
/**
* @Assert\Callback
*/
public function validateFields(ExecutionContextInterface $context)
{
if ('' === $this->fieldA && '' === $this->fieldB && '' === $this->fieldC) {
$context->addViolation('At least one of the fields must be filled');
}
}
该方法将在类的验证期间执行。
【讨论】:
这可能是Custom Validation Constraint 的一个用例。我自己没有使用它,但基本上你创建了一个Constraint 和一个Validator。然后,您在 config/validation.yml 中指定您的 Constraint。
Your\Bundle\Entity\YourEntity:
constraints:
- Your\BundleValidator\Constraints\YourConstraint: ~
实际验证由您的Validator 完成。您可以告诉 Symfony 将整个实体传递给您的 validate 方法以访问多个字段:
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
还有你的validate:
public function validate($entity, Constraint $constraint)
{
// Do whatever validation you need
// You can specify an error message inside your Constraint
if (/* $entity->getFieldA(), ->getFieldB(), ->getFieldC() ... */) {
$this->context->addViolationAt(
'foo',
$constraint->message,
array(),
null
);
}
}
【讨论】:
您可以使用Group Sequence Providers 执行此操作,例如:
use Symfony\Component\Validator\GroupSequenceProviderInterface;
/**
* @Assert\GroupSequenceProvider
*/
class MyObject implements GroupSequenceProviderInterface
{
/**
* @Assert\NotBlank(groups={"OptionA"})
*/
private $fieldA;
/**
* @Assert\NotBlank(groups={"OptionA"})
*/
private $fieldB;
/**
* @Assert\NotBlank(groups={"OptionB"})
*/
private $fieldC;
public function getGroupSequence()
{
$groups = array('MyObject');
if ($this->fieldA == null && $this->fieldB == null) {
$groups[] = 'OptionB';
} else {
$groups[] = 'OptionA';
}
return $groups;
}
}
未测试,但我认为它会工作
【讨论】: