2011-11-17 17 views
13

Obecnie tworzę stronę internetową, na której użytkownik może kupować karty podarunkowe. Używam trzyetapowego formularza przy użyciu pakietu CraueFormFlow i wszystko dotyczy kroków. Potrafię potwierdzić każde proste stwierdzenie (jak nie puste, e-mail, powtarzające się pola itp.), Ale mam do czynienia z sytuacją, w której użytkownik może wybrać 0 kart podarunkowych i przejść do następnej strony.Zatwierdzenie formularza Symfony2 na podstawie dwóch pól

Użytkownicy mogą wybrać ilość kart podarunkowych, które chcą kupić za pomocą dwóch oddzielnych kart: jednej na karty podarunkowe 25 $ i jednej za karty podarunkowe 50 $. Więc nie mogę po prostu wstawić walidatora mówiącego "wartość 0 jest niedozwolona". Walidator musi uniemożliwić użytkownikowi pozostawienie liczby "0" w obu kwotach (25 $ i 50 $).

Czy ktoś wie, jak dokonać niestandardowego sprawdzania poprawności, szukając wartości w dwóch polach?

Z góry dziękuję!

Odpowiedz

30

Masz wiele rozwiązań w tym zakresie.

Najprostszym sposobem jest dodanie do klasy modelu Callback constraint.

Innym sposobem na zrobienie tego byłoby utworzenie niestandardowego ograniczenia i związanego z nim walidatora. Masz cookbook explaining how to create a custom validation constrain. Jest to najlepsze podejście do tego.

Jako twój ograniczenie nie ma zastosowania do nieruchomości, ale do klasy, należy określić to nadpisanie metody ->getTargets() swojej klasie więzów:

class MyConstraint extends Constraint 
{ 
    // ... 

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

Więc wartość przekazana jako $value argumentu metody ->isValid() będzie zawierał wartości całej klasy, a nie tylko jednej własności.

+3

Proszę wyjaśnić mi, jak zastosować ograniczenie wywołania zwrotnego? Patrzę na dokument Symfony2 i nie bardzo wiem, jak uzyskać dostęp do wartości, które chcę sprawdzić w funkcji [...] isValid(). –

+0

Wygląda na to, że nie działa, gdy nie ma klasy danych (podczas pracy z tablicami). – umpirsky

3

regularne wyrażenie Inorder aby zapobiec Zero

W swojej klasie Entity napisać funkcję nadpisywania poniżej i określić swoją właściwość które trzeba zweryfikować.

Poniższy przykład służy do sprawdzania kodu PIN, tutaj w polu kodu PIN przyznaję tylko cyfry 0-9 kombinacji do 10 cyfr.

"^ \ d + $" jest to wyrażenie regularne, którego użyłem do uniknięcia innych znaków.

nadrzędne tej funkcji należy uwzględnić poniższe zajęcia

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


    } 

Nie zapomnieć te wszystkie muszą

zawarte w klasie Entity

że trzeba zweryfikować. Więc w twoim przypadku użyj właściwego wyrażenia regularnego, które nie pozwala na "0".

Szczęśliwy kodowania

12

Kiedy nie masz klasę danych dołączony do formularza można wdrożyć ograniczenia zależne od formy tak:

$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

i co jeśli muszę uzyskać dostęp do entityManger? –

5

to jak robiłem to w moim ograniczenia sprawdzania poprawności, aby sprawdzić ważność karty kredytowej z właściwościami miesiąca i roku wygaśnięcia.

W tej klasie sprawdzam wartość właściwości expirationYear i porównuję ją z wartością właściwości expirationMonth pobranej z 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; 
} 

Oczywiście, trzeba zezwolić ograniczeń klasowych i właściwości w metodzie getTargets tworzą główny plik wiązania.

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

Dalsze wyjaśnienia i kompletny poradnik tutaj: http://creativcoders.wordpress.com/2014/07/19/symfony2-two-fields-comparison-with-custom-validation-constraints/

3

Sugeruję użyciu Expression constraint. To ograniczenie może być stosowane na polu formularza lub (najlepiej) w podmiocie:

/** 
    * @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; 
Powiązane problemy