交响乐 3 | CollectionType 实体的自定义约束

Symfony 3 | Custom constraints on CollectionType entities

我按照文档进行操作,并能够在我的许多字段上添加自定义约束 (http://symfony.com/doc/current/validation/custom_constraint.html)。

我发现 CollectionType 字段有问题。 我的自定义约束只是检查用户是否没有在字段中点击多个 space(无论如何约束都不重要)。

我有一个带有标题和答案的问题表:

$builder
    ->add('title', TextType::class)
    ->add('answers', CollectionType::class, array(
            'entry_type'    => AnswerType::class,
            'allow_add'     => true,
            'allow_delete'  => true,
            'by_reference' => false
        ))

我有我的限制:

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class ContainsText extends Constraint
{
    public $message = 'constraint_error';
}

我的约束验证器:

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

class ContainsTextValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        // It checks if user didn't had multiple space in field
        if (strlen(trim($value)) == 0) {
            $this->context->buildViolation($constraint->message)
                ->addViolation();
        }
    }
}

在我的实体中:

问题:

use XX\XXBundle\Validator\Constraints as CustomAssert;    

class Question 
{
    /**
     * @var string
     *
     * @ORM\Column(name="title", type="string", length=255, unique=true)
     * @CustomAssert\ContainsText    
     */
    private $title;
    ...
}

答案:

use XX\XXBundle\Validator\Constraints as CustomAssert; 

class Answer 
{
    /**
     * @var string
     *
     * @ORM\Column(name="text", type="string", length=255, unique=true)
     * @CustomAssert\ContainsText    
     */
    private $text;
    ...
}

在我的表单验证中,如果我在问题标题中点击了很多 space,我会收到表单验证错误以及 "constraint_error" 消息 => 一切正常。

但是,如果我在问题答案文本中点击许多 space,表单验证不会 return 任何错误,并且我的问题是用空答案创建的!

似乎,如果该字段来自 CollectionType,则自定义断言将被忽略。

我不明白的是,如果我在答案文本上有一个断言(如@Assert\Blank(),而不是自定义断言),即使我们在 CollectionType 中,断言也不是被忽略,我无法验证一个空白答案的表单。

我在这里错过了什么? TY

不确定您使用的是哪个 Symfony 2 版本,但取决于它是 pre 2.8 还是更高版本,您有不同的方法来解决这个问题:

v2.8+ 和 v3.0+

v2.8 开始,我怀疑您可能会使用 AnswerType::classcascade_validation 已弃用。相反,您需要对 Question::$answers class 成员应用 Valid 约束。像这样:

class Question 
{
    /**
     * ... Other anotaions go here 
     *
     * @Assert\Valid()
     */
    private $answers
}

v2.8 之前的版本:

您需要指定cascade_validation选项:

$builder
    ->add('title', TextType::class)
    ->add('answers', CollectionType::class, array(
            'entry_type'    => AnswerType::class,
            'allow_add'     => true,
            'allow_delete'  => true,
            'by_reference' => false,
            'cascade_validation' => true // <========= THIS
        ));

希望这对您有所帮助...