2011-11-17 20 views
13

Actualmente estoy desarrollando un sitio web en el que el usuario puede comprar tarjetas de regalo. Estoy usando una forma de tres pasos usando el paquete CraueFormFlow y todo está relacionado con los pasos. Puedo validar cada Assert simple (como no en blanco, correo electrónico, campos repetidos, etc.) pero estoy enfrentando la situación en la que el usuario puede seleccionar 0 tarjetas de regalo y pasar a la página siguiente.Validación del formulario Symfony2 basada en dos campos

Los usuarios pueden elegir la cantidad de tarjetas de regalo que desean comprar utilizando dos tarjetas de regalo separadas: una por 25 $ y una por 50 $. Así que no puedo simplemente poner un validador que diga "valor 0 no está permitido". El validador debe evitar que un usuario deje la cantidad "0" en ambas cantidades (25 $ y 50 $).

¿Alguien sabe cómo hacer una validación personalizada buscando los valores en dos campos?

¡Gracias de antemano!

Respuesta

30

Tiene muchas soluciones para esto.

La más fácil es agregar un Callback constraint a su clase de modelo.

Otra forma de hacerlo sería crear su restricción personalizada y su validador asociado. Usted tiene un cookbook explaining how to create a custom validation constrain. Este es el mejor enfoque para hacerlo.

medida que su limitación no se aplica a una propiedad, sino a una clase, debe especificar que reemplazando el método ->getTargets() de su clase de restricción:

class MyConstraint extends Constraint 
{ 
    // ... 

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

Así que el valor pasa como $value argumento del método ->isValid() contendrá valores de toda la clase y no solo de una sola propiedad.

+3

¿Me podría explicar cómo implementar la restricción de devolución de llamada? Estoy mirando el documento de Symfony2 y no sé cómo acceder a los valores que quiero verificar en la función [...] isValid(). –

+0

Parece que no funciona cuando no hay clase de datos (cuando se trabaja con matrices). – umpirsky

3

Uso de expresiones regulares finde para evitar Cero

En su clase de entidad anote la función de anulación de abajo, y especificar su propiedad que necesita para validar.

El siguiente ejemplo es para validar un código PIN, aquí en el campo de código PIN Admito solo números de 0 a 9 combinaciones de hasta 10 dígitos.

"^ \ d + $" esta es la expresión regular que utilicé para evitar otros caracteres.

para anular esta función debe incluir las siguientes clases

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


    } 

No se olvide de estos todo imprescindible

incluidos en la clase de entidad

que usted tiene que validar. Entonces, en su caso, use una expresión regular adecuada que no permita '0'.

feliz de codificación

12

Cuando usted no tiene una clase de datos conectado a su forma se puede aplicar restricciones dependientes en formas como esto:

$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

y ¿qué sucede si también necesito acceder a entityManger? –

5

Así es como yo he hecho esto en mi Restricciones de validación, para verificar la validez de la tarjeta de crédito con las propiedades de vencimiento del mes y el año.

En esta clase, compruebo el valor de la propiedad expirationYear y la comparo con el valor de la propiedad expirationMonth obtenida de 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; 
} 

Por supuesto, usted tiene que autorizar a las limitaciones de clase y propiedades en su método de getTargets, forman el archivo principal limitación.

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

Más explicaciones y tutorial completo aquí: http://creativcoders.wordpress.com/2014/07/19/symfony2-two-fields-comparison-with-custom-validation-constraints/

3

me gustaría sugerir el uso de Expression constraint. Esta restricción puede ser aplicado en campo de formulario o (preferiblemente) en la entidad:

/** 
    * @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; 
Cuestiones relacionadas