【问题标题】:Symfony Form Validation Constraint ExpressionSymfony 表单验证约束表达式
【发布时间】:2017-03-10 07:04:24
【问题描述】:

我有表单,需要创建内联验证:

$builder
        ->add('Count1', 'integer', [
            'data'        => 1,
            'constraints' => [
                new NotBlank(),
                new NotNull(),
            ],
        ])
        ->add('Count2', 'integer', [
            'constraints' => [
                new NotBlank(),
                new NotNull(),
            ],
        ])
        ->add('Count3', 'integer', [
            'data'        => 0,
            'constraints' => [
                new NotBlank(),
                new NotNull(),
            ],
        ])

如何白内联验证表达式的规则

  1. Count2 >=Count1
  2. Count3
  3. Count2 >= $someVariable

【问题讨论】:

    标签: validation symfony symfony-forms symfony-validator


    【解决方案1】:

    您可以使用CallbackValidator (docs):

    在您的情况下,为了验证一个字段与另一个字段,您需要将约束添加到表单类型,而不是字段:

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'constraints' => array(
                new Assert\Callback(function($data){
                    // $data is instance of object (or array) with all properties
                    // you can compare Count1, Count2 and Count 3 
                    // and raise validation errors
                });
            )
        ));
    }
    

    如果您不想在setDefaultOptions 中设置,也可以在创建表单时传递constraints 选项。

    【讨论】:

    • 请注意:从 symfony 3 开始,您应该使用 configureOptions。我写这个 setDefaultOptions 默默地失败(因为它只是一个简单的名字)
    • @DonCallisto 非常好。上面的方法首先被弃用,然后完全删除......
    • 请用那些版本的 symfony 来更新你的答案:太好了! :)
    【解决方案2】:

    从最简单的开始

    3) Count2 >= $someVariable

        ->add('Count3', 'integer', [
            'data'        => 0,
            'constraints' => [
                new NotBlank(),
                new NotNull(),
                new GreaterThanOrEqual($someVariable),
            ],
        ])
    

    1) 至于前两个,你必须为类作用域实现约束,而不是属性作用域。并为整个表单分配这些约束

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
       $builder
        ->add('Count1', 'integer', [
            'data'        => 1,
            'constraints' => [
                new NotBlank(),
                new NotNull(),
            ],
        ])
        ->add('Count2', 'integer', [
            'constraints' => [
                new NotBlank(),
                new NotNull(),
            ],
        ])
        ->add('Count3', 'integer', [
            'data'        => 0,
            'constraints' => [
                new NotBlank(),
                new NotNull(),
            ],
        ])
    }
    
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
         $resolver->setDefaults(['constraints' => [
                new YourCustomConstraint(),
              ]]);
    }
    

    如何实现验证器,见the documentation。 但是在你的YourCustomConstraintValidator 中你会有类似的东西

    public function validate($value, Constraint $constraint)
    {
         if ($value->getCount1() > $value->getCount2() {
               $this->context->addViolation(...);
         }
    }
    

    【讨论】:

    • 请注意:从 symfony 3 开始你应该使用configureOptions。我写这个 setDefaultOptions 默默地失败了(因为它只是一个简单的名字)
    【解决方案3】:

    在案例 1 和案例 2 中使用 Expression Constraint 的其他解决方案。

    use Symfony\Component\Validator\Constraints as Assert;
    
    // ...
    
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'constraints' => [
                new Assert\Expression([
                    'expression' => 'value["Count2"] >= value["Count1"]',
                    'message' => 'count2 must be greater than or equal to count1'
                ]),
                new Assert\Expression([
                    'expression' => 'value["Count3"] <= value["Count2"]',
                    'message' => 'count3 must be less than or equal to count2'
                ]),
            ],
        ]);
    }
    

    对于案例 3,您可以直接在 Count2 字段上使用 Assert\GreaterThanOrEqual 约束。

    我猜你的表单没有绑定对象模型,否则阅读 the documentation 引用就足够了,而且更好,因为你可以直接在你的属性上使用这些表达式。

    【讨论】:

    • 我其实比我自己更喜欢这个答案=)
    • 请注意:从 symfony 3 开始你应该使用configureOptions。我写这个 setDefaultOptions 默默地失败了(因为它只是一个简单的名字)
    【解决方案4】:

    我在使用 Symfony 的表达式比较两个日期时遇到了一些问题。

    这是有效的代码:

     $builder->add(
                'end',
                DateTimeType::class,
                [
                    'label' => 'Campaign Ends At',
                    'data' => $entity->getEnd(),
                    'required' => true,
                    'disabled' => $disabled,
                    'widget'  => 'single_text',
                    'constraints' => [
                        new Assert\GreaterThan(['value' => 'today']),
                        new Assert\Expression(
                                    [
                                        //here end and start are the name of two fields
                                        'expression' => 'value > this.getParent()["start"].getData()',
                                        'message' => 'my.form.error.end.date.bigger.than.start'
                                    ]
                                ),
                    ]
    
                ]
            );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-10
      相关资源
      最近更新 更多