2011-11-17 80 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;