2012-09-04 5 views
27

¿Es posible validar una propiedad de una clase de modelo dependiente de otra propiedad de la misma clase?Cómo validar una propiedad dependiente de otra propiedad en Symfony 2

Por ejemplo, tengo esta clase:

class Conference 
{ 
    /** $startDate datetime */ 
    protected $startDate; 

    /** $endDate datetime */ 
    protected $endDate; 
} 

y quiero que Symfony 2.0 valida, que $startDate tiene que ser después $endDate.

¿Esto es posible mediante anotaciones o tengo que hacerlo manualmente?

Respuesta

19

Sí con el validador de devolución de llamada: http://symfony.com/doc/current/reference/constraints/Callback.html

En Symfony 2.0:

use Symfony\Component\Validator\Constraints as Assert; 
use Symfony\Component\Validator\ExecutionContext; 

/** 
* @Assert\Callback(methods={"isDateValid"}) 
*/ 
class Conference 
{ 

    // Properties, getter, setter ... 

    public function isDateValid(ExecutionContext $context) 
    { 
     if ($this->startDate->getTimestamp() > $this->endDate->getTimestamp()) { 
       $propertyPath = $context->getPropertyPath() . '.startDate'; 
       $context->setPropertyPath($propertyPath); 
       $context->addViolation('The starting date must be anterior than the ending date !', array(), null); 
     } 
    } 
} 

En Symfony versión maestra:

public function isDateValid(ExecutionContext $context) 
    { 
     if ($this->startDate->getTimestamp() > $this->endDate->getTimestamp()) { 
      $context->addViolationAtSubPath('startDate', 'The starting date must be anterior than the ending date !', array(), null); 
     } 
    } 

Aquí me eligen para mostrar el mensaje de error en el campo startDate .

+0

Marcó la respuesta de @Sykehoe, que debería ser un comentario en lugar de una respuesta, por lo tanto, reformulando su comentario aquí. 'addViolationAtSubPath' está en desuso desde la versión 2.2, use [addViolationAt] (http://api.symfony.com/2.3/Symfony/Component/Validator/ExecutionContextInterface.html#method_addViolationAt) en su lugar. – astorije

9

Es aún más simple desde version 2.4. Todo lo que tiene que hacer es añadir este método a su clase:

use Symfony\Component\Validator\Context\ExecutionContextInterface; 

/** 
* @Assert\Callback 
*/ 
public function isStartBeforeEnd(ExecutionContextInterface $context) 
{ 
    if ($this->getStartDate() <= $this->getEndDate()) { 
     $context->buildViolation('The start date must be prior to the end date.') 
       ->atPath('startDate') 
       ->addViolation(); 
    } 
} 

Los buildViolation method Devuelve un creador que tiene un par de otros métodos para ayudarle a configurar la restricción (como parámetros y traducción).

36

A partir de Symfony 2.4 también puede usar Expression restricción de validación para lograr lo que necesita. Creo que esta es la manera más simple de hacer esto. Es más conveniente que la restricción de devolución de llamada con seguridad.

Aquí es ejemplo de cómo se puede actualizar la clase del modelo con restricciones de validación anotaciones:

use Symfony\Component\Validator\Constraints as Assert; 


class Conference 
{ 
    /** 
    * @var \DateTime 
    * 
    * @Assert\Expression(
    *  "this.startDate <= this.endDate", 
    *  message="Start date should be less or equal to end date!" 
    *) 
    */ 
    protected $startDate; 

    /** 
    * @var \DateTime 
    * 
    * @Assert\Expression(
    *  "this.endDate >= this.startDate", 
    *  message="End date should be greater or equal to start date!" 
    *) 
    */ 
    protected $endDate; 
} 

No se olvide de enable annotations en la configuración del proyecto.

Siempre puede hacer validaciones aún más complejas usando expression syntax.

10

Otra forma (al menos como de Symfony 2.3) es utilizar sencilla @Assert\IsTrue:

class Conference 
{ 
    //... 

    /** 
    * @Assert\IsTrue(message = "Startime should be lesser than EndTime") 
    */ 
    public function isStartBeforeEnd() 
    { 
     return $this->getStartDate() <= $this->getEndDate; 
    } 

    //... 
} 

Como referencia, documentation.

+1

@Asert \ True ha existido desde Symfony 2.0, sin embargo, debe usar @Assert \ IsTrue de Symfony 2.3 –

+0

@DanielP: Sí, 2.3 agregó'Asertar \ IsTrue '. '@Assert \ True' en desuso desde 2.7. Actualizado, gracias. – Nevertheless

Cuestiones relacionadas