2011-11-17 83 views
13

我目前正在开发一个用户可以购买礼品卡的网站。我正在使用使用CraueFormFlow包的三步表单,并且所有步骤都与步骤有关。我可以验证每个简单的Assert(如不是空白,电子邮件,重复字段等),但我面临的情况是,用户可以选择0张礼品卡并进入下一页。基于两个字段的Symfony2表单验证

用户可以选择他们想要购买的礼品卡的数量,使用两个单独的礼品卡:一个用于25美元的礼品卡和一个用于50美元的礼品卡。所以我不能只让一个验证者说“不允许值0”。验证器必须防止用户以两个数量(25 $和50 $)保留数量“0”。

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

在此先感谢!

回答

30

你有很多解决方案。

最简单的方法是在您的模型类中添加一个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参数传递将包含整个班级的价值,而不仅仅是一个单一的财产。

+3

请问您能解释一下如何实现回调约束吗?我正在查看Symfony2文档,我不知道如何访问我想检查isValid()函数的值。 –

+0

当没有数据类时(当您使用数组时),它看起来不起作用。 – umpirsky

3

使用正则表达式序,以防止零

在你的实体类写下下面的重载函数,并指定你的财产,你需要验证。

以下示例用于验证PIN码,在pincode字段中,我只允许数字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'的适当的正则表达式。

快乐编码

12

当你没有连接到你的表单数据类可以实现这样的形式从属约束:

$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, 

     ) 
    ); 
+0

以及如果我需要访问entityManger呢? –

5

这是我如何做这个我验证限制,以检查信用卡有效期和过期月和年的属性。

在这个类中,我检查expirationYear属性的值,并将其与从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/

3

我建议使用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;