2011-11-17 33 views
13

Tôi hiện đang phát triển một Trang web mà trong đó người dùng có thể mua thẻ quà tặng. Tôi đang sử dụng một hình thức ba bước bằng cách sử dụng bó CraueFormFlow và tất cả mọi thứ liên quan đến các bước. Tôi có thể xác nhận mọi xác nhận đơn giản (như không trống, email, các trường lặp lại, v.v.) nhưng tôi đang đối mặt với tình huống ở đó, người dùng có thể chọn 0 thẻ quà tặng và chuyển sang trang tiếp theo.Xác thực biểu mẫu Symfony2 dựa trên hai trường

Người dùng có thể chọn số lượng thẻ quà tặng họ muốn mua bằng hai thẻ riêng biệt: một cho 25 thẻ quà tặng và một cho 50 thẻ quà tặng $. Vì vậy, tôi không thể chỉ cần đặt một validator nói "giá trị 0 là không được phép". Trình xác thực phải ngăn người dùng để lại số lượng "0" trong cả hai số tiền (25 $ và 50 $).

Có ai biết cách thực hiện xác thực tùy chỉnh tìm kiếm các giá trị trong hai trường không?

Cảm ơn trước!

Trả lời

30

Bạn có nhiều giải pháp cho việc này.

Cách dễ nhất là thêm Callback constraint vào lớp mô hình của bạn.

Một cách khác để thực hiện việc đó là tạo ràng buộc tùy chỉnh và trình xác thực được liên kết. Bạn có một cookbook explaining how to create a custom validation constrain. Đây là phương pháp tốt nhất để làm điều đó.

Như hạn chế của bạn không áp dụng đối với một tài sản nhưng để một lớp, bạn phải xác định nó trọng các phương pháp ->getTargets() của lớp hạn chế của bạn:

class MyConstraint extends Constraint 
{ 
    // ... 

    public function getTargets() 
    { 
     return Constraint::CLASS_CONSTRAINT; 
    } 
} 

Vì vậy, các giá trị truyền như $value đối số của phương pháp ->isValid() sẽ chứa các giá trị của cả lớp và không chỉ của một thuộc tính duy nhất.

+3

Bạn có thể giải thích cho tôi cách triển khai ràng buộc gọi lại không? Tôi đang nhìn vào tài liệu Symfony2 và tôi không hoàn toàn biết cách truy cập các giá trị mà tôi muốn kiểm tra trong hàm [...] isValid(). –

+0

Có vẻ như nó không hoạt động khi không có lớp dữ liệu (khi bạn làm việc với các mảng). – umpirsky

3

Sử dụng cụm từ thông dụng để ngăn chặn Zero

Trong lớp Entity của bạn viết hàm ghi đè bên dưới và chỉ định thuộc tính bạn cần xác thực.

Ví dụ bên dưới là để xác thực mã PIN, ở đây trong trường mã hóa Tôi chỉ chấp nhận số 0-9 kết hợp tối đa 10 chữ số.

"^ \ d + $" đây là cụm từ thông dụng tôi đã sử dụng để ngăn các ký tự khác.

Đối trọng chức năng này, bạn phải bao gồm các lớp bên dưới

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'))); 


    } 

Không quên những tất cả phải

bao gồm trong lớp Entity bạn

mà bạn phải xác nhận. Vì vậy, trong trường hợp của bạn sử dụng một biểu thức chính quy thích hợp mà không cho phép '0'.

Chúc mừng mã hóa

12

Khi bạn không có một lớp dữ liệu gắn liền với hình thức của bạn, bạn có thể thực hiện những hạn chế phụ thuộc vào hình thức như thế này:

$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

và nếu tôi cần truy cập entityManger thì sao? –

5

này là làm thế nào tôi đã làm điều này trong tôi các ràng buộc xác nhận, để kiểm tra tính hợp lệ của thẻ tín dụng với các thuộc tính tháng và năm hết hạn.

Trong lớp này, tôi kiểm tra giá trị của thuộc tính expirationYear và so sánh giá trị với thuộc tính expirationMonth nhận được từ contextObject.

/** 
* 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; 
} 

Tất nhiên, bạn phải cho phép hạn chế lớp và các thuộc tính trong phương pháp getTargets của bạn, hình thành các tập tin trở ngại chính.

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

giải thích sâu hơn và đầy đủ hướng dẫn ở đây: http://creativcoders.wordpress.com/2014/07/19/symfony2-two-fields-comparison-with-custom-validation-constraints/

3

tôi muốn đề nghị sử dụng Expression constraint. Ràng buộc này có thể được áp dụng trên trường biểu mẫu hoặc (tốt nhất) trong thực thể:

/** 
    * @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; 
Các vấn đề liên quan