【问题标题】:Symfony2 form validation based on two fieldsSymfony2 基于两个字段的表单验证
【发布时间】:2011-12-31 12:02:23
【问题描述】:

我目前正在开发一个网站,用户可以在其中购买礼品卡。我正在使用 CraueFormFlow 捆绑包使用三步表单,一切都与步骤有关。我能够验证每个简单的断言(如非空白、电子邮件、重复字段等),但我面临的情况是,用户可以选择 0 张礼品卡并进入下一页。

用户可以使用两种不同的方式选择他们想要购买的礼品卡数量:一张用于 25 美元的礼品卡,一张用于 50 美元的礼品卡。所以我不能只放一个验证器说“不允许值 0”。验证器必须防止用户在两个金额(25 美元和 50 美元)中都留下数量“0”。

有谁知道如何进行自定义验证以查找两个字段中的值?

提前致谢!

【问题讨论】:

    标签: forms validation symfony


    【解决方案1】:

    你有很多解决方案。

    最简单的方法是将Callback constraint 添加到您的模型类中。

    另一种方法是创建您的自定义约束及其关联的验证器。你有一个cookbook explaining how to create a custom validation constrain。 这是最好的方法。

    由于您的约束不适用于属性而是应用于类,因此您必须指定它来覆盖约束类的 ->getTargets() 方法:

    class MyConstraint extends Constraint
    {
        // ...
    
        public function getTargets()
        {
            return Constraint::CLASS_CONSTRAINT;
        }
    }
    

    因此,作为->isValid() 方法的$value 参数传递的值将包含整个类的值,而不仅仅是单个属性的值。

    【讨论】:

    • 你能解释一下如何实现回调约束吗?我正在查看 Symfony2 文档,但我不太清楚如何访问要在 [...]isValid() 函数中检查的值。
    • 在没有数据类的情况下(使用数组时)似乎不起作用。
    【解决方案2】:

    使用正则表达式来防止归零

    在您的实体类中写下以下覆盖函数,并指定您需要验证的属性。

    以下示例用于验证密码,在此密码字段中,我只承认数字 0-9 组合最多 10 位。

    " ^\d+$ " 这是我用来阻止其他字符的正则表达式。

    要覆盖此函数,您必须包含以下类

    use Symfony\Component\Validator\Mapping\ClassMetadata;// for overriding function loadValidatorMetadata()
    
    use Symfony\Component\Validator\Constraints\NotBlank;// for notblank constrain
    
    use Symfony\Component\Validator\Constraints\Email;//for email constrain
    
    use Symfony\Component\Validator\Constraints\MinLength;// for minimum length
    
    use Symfony\Component\Validator\Constraints\MaxLength; // for maximum length
    
    use Symfony\Component\Validator\Constraints\Choice; // for choice fields
    
    use Symfony\Component\Validator\Constraints\Regex; // for regular expression
    
    
    
    public static function loadValidatorMetadata(ClassMetadata $metadata)
        {
            $metadata->addPropertyConstraint('pincode', new NotBlank(array('message' => 'Does not blank')));
            $metadata->addPropertyConstraint('pincode', new Regex(array('pattern'=>'/^\d+$/','message' => 'must be number')));
            $metadata->addPropertyConstraint('pincode', new MaxLength(array('limit'=>'6','message' => 'must maximum 6 digits')));
            $metadata->addPropertyConstraint('pincode', new MinLength(array('limit'=>'6','message' => 'must minimum 6 digits')));
    
    
        }
    

    不要忘记这些都是必须的

    包含在您的实体类中

    您必须验证。因此,在您的情况下,请使用不允许“0”的正确正则表达式。

    快乐编码

    【讨论】:

      【解决方案3】:

      当您的表单没有附加数据类时,您可以在表单中实现依赖约束,如下所示:

          $startRangeCallback = function ($object, ExecutionContextInterface $context) use ($form)
          {
              $data = $form->getData();
              $rangeEnd = $data['range_end'];
              if($object && $rangeEnd){
                  if ($object->getTimestamp() > $rangeEnd->getTimestamp()) {
                      $context->addViolation('Start date should be before end date!', array(), null);
                  }
              }
      
          };
      
          $form->add('range_start', 'bootstrap_datepicker', array(
                  'format' => 'dd-MM-yyyy',
                  'required' => false,
                  'attr' => array('class' => "col-xs-2"),
                  'calendar_weeks' => true,
                  'clear_btn' => true,
                  'constraints' => array(
                      new Callback(array($startRangeCallback)),
                  )
              )
          );
      
          $form->add('range_end', 'bootstrap_datepicker', array(
                  'format' => 'dd-MM-yyyy',
                  'required' => false,
                  'attr' => array('class' => "col-xs-2"),
                  'calendar_weeks' => true,
                  'clear_btn' => true,
      
              )
          );
      

      【讨论】:

      • 如果我也需要访问 entityManger 怎么办?
      【解决方案4】:

      这就是我在验证约束中执行此操作的方式,以使用到期月份和年份属性检查信用卡有效性。

      在这个类中,我检查了 expireYear 属性的值,并将其与从 contextObject 获取的 expirationMonth 属性的值进行比较。

      /**
       * Method to validate
       * 
       * @param string                                  $value      Property value    
       * @param \Symfony\Component\Validator\Constraint $constraint All properties
       * 
       * @return boolean
       */
      public function validate($value, Constraint $constraint)
      {
          $date               = getdate();
          $year               = (string) $date['year'];
          $month              = (string) $date['mon'];
      
          $yearLastDigits     = substr($year, 2);
          $monthLastDigits    = $month;
          $otherFieldValue    = $this->context->getRoot()->get('expirationMonth')->getData();
      
          if (!empty($otherFieldValue) && ($value <= $yearLastDigits) && 
                  ($otherFieldValue <= $monthLastDigits)) {
              $this->context->addViolation(
                  $constraint->message,
                  array('%string%' => $value)
              );            
              return false;            
          }
      
          return true;
      }
      

      当然,您必须在 getTargets 方法中授权类和属性约束,形成主约束文件。

      /**
       * Get class constraints and properties
       * 
       * @return array
       */
      public function getTargets()
      {
          return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT);
      } 
      

      进一步的解释和完整的教程在这里:http://creativcoders.wordpress.com/2014/07/19/symfony2-two-fields-comparison-with-custom-validation-constraints/

      【讨论】:

        【解决方案5】:

        我建议使用Expression constraint。此约束可以应用于表单字段或(最好)在实体中:

           /**
             * @var int
             * @Assert\Type(type="integer")
             */
            private $amountGiftCards25;
        
            /**
             * @var int
             * @Assert\Type(type="integer")
             * @Assert\Expression(expression="this.getAmountGiftCards25() > 0 or value > 0", message="Please choose amount of gift cards.")
             */
            private $amountGiftCards50;
        

        【讨论】:

          猜你喜欢
          • 2021-11-18
          • 1970-01-01
          • 2015-07-24
          • 2017-06-24
          • 2021-07-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-18
          相关资源
          最近更新 更多