如何修改Symfony2中自定义验证器中的回调(.7)

时间:2015-09-12 18:09:33

标签: forms validation symfony

标题可能看起来很尴尬,但这样做的原因是重复使用代码。

假设我有一个表单(类型),一个实体以及对实体的验证作为注释。

例如:

表单:

$form = $this->createFormBuilder($entity)
    ->add('country', 'choice', [
        'choices' => $entity->getLocations(),
        'required' => true,
        'multiple' => false,
        'expanded' => false,
        'label' => 'Are you located in:',
    ])

实体:

/**
 * @Assert\Choice(callback = "getLocations")
 */
protected $country;

#.....

public static function getLocations()
{
    return array( 'en-wa' => 'England/Wales', 'sc' => 'Scotland');
}

现在验证将始终失败,因为它使用值而不是键,所以我想写一个名为KeyChoice的自定义验证器,所以我仍然可以使用回调。但我似乎无法找到任何关于此的文档,阅读源代码也没有帮助。

现在我不想要对最佳实践做出判断,除非有一种方法我只需要定义选项1 /表格甚至更少,例如在表单类型中,但是我如何使用它们在验证器的回调中?

1 个答案:

答案 0 :(得分:1)

这个怎么样:

/**
 * @Assert/Choice(callback="getLocationChoices")
 */
 ...

 public static function getLocationChoices(){

  return array_keys(self::getLocations());
 }

更新

或者您可以为此创建custom constraint

// the constraint
namespace AppBundle\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class KeyChoice extends Constraint
{
    public $message = 'the choice is not valid';
    public $callback;
}

// the validator
namespace AppBundle\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

class KeyChoiceValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        if (!is_callable($choices = array($this->context->getClassName(), $constraint->callback))
            && !is_callable($choices = $constraint->callback)
        ) {
            throw new ConstraintDefinitionException('The Choice constraint expects a valid callback');
        }
        $choices = call_user_func($choices);   
        if(!in_array($value, $choices)){
          $this->context->buildViolation($constraint->message)->addViolation();
        }    
    }
}

然后您可以使用链接文档中所述的此约束。但是,如果您想要扩展两者,则不会提供选择约束提供的任何其他功能。 Symfony\Component\Validator\Constraints\ChoiceSymfony\Component\Validator\Constraints\ChoiceValidator,请勿覆盖ChoiceConstraint中的任何内容,但您必须完全覆盖ChoiceConstraintValidator::validate并复制粘贴,然后添加$choices = array_keys($choices); this line