2011-09-22 30 views
21

Me gustaría aplicar validadores en las propiedades de un objeto solo cuando el valor no está vacío, es decir.Cómo permitir valores vacíos en los validadores de Symfony2

Ahora estándar de comportamiento de Symfony:

class Entity 
{ 
    /** 
    * @ORM\Column(type="string", nullable=true) 
    * @Assert\Email() 
    */ 
    protected $email; 
    (...) 
} 

que el objeto no pasará la validación si un correo electrónico es nulo, o cadena vacía, ¿hay una manera de contar validador de hacer valer como válido, un valor vacío, y validar solo si el campo tiene datos?

PD Sé que puedo escribir el validador de devolución de llamada, pero escribir la devolución de llamada para cada campo solo para tener la función "allowEmpty" no es tan agradable.

Respuesta

22

Debe establecer explícitamente 'required' => false en su clase FormBuilder para todos los campos opcionales. Aquí hay un párrafo que describe field type options.


Editar. Obteniendo algunos votos a la baja. Por defecto todos los validadores tratan los valores null como válidos, exceptoNotNull y NotEmpty. Ninguno de los dos fue utilizado en la pregunta. La pregunta es implícita sobre cómo desactivar el atributo required del lado del cliente que está activado de manera predeterminada.

+26

Esta no es la respuesta correcta. La opción "requerida" impone solo la validación del lado del cliente. – TyrionLannister

+7

@TyrionLannister Estás en lo cierto. Sin embargo, ninguno de los validadores predeterminados da como resultado que un valor vacío se trate como inválido, excepto cuando se tienen restricciones 'NotNull()' y 'NotEmpty()'. Viendo que el asker no tenía ninguna de esas restricciones, estaba implícito que el problema era con el atributo HTML5 'required' del lado del cliente. – gilden

+3

@gilden con todo el debido respeto, el atributo 'required' no tiene nada en común con el valor vacío aprobado. Solo se utiliza mediante la validación del lado del cliente HTML5 y no está relacionada con la validación (la del lado del servidor). –

19

se establece la opción required no es la solución:

También tenga en cuenta que la fijación de la opción requerida para cierto no dará lugar a la validación del lado del servidor que debe aplicarse. En otras palabras, si un usuario envía un valor en blanco para el campo (ya sea con un navegador o servicio web antiguo, por ejemplo), se aceptará como un valor válido a menos que use la restricción de validación NotBlank o NotNull de Symfony.

http://symfony.com/doc/current/book/forms.html#field-type-options

Para mis validadores personalizados, agrego un

if (null == $value) { 
    return true; 
} 

al método isValid(). Sin embargo, no estoy seguro de cuál sería la mejor forma para las clases de validador estándar.

+1

esta debería ser la respuesta aceptada, porque la respuesta aceptada solo se aplica para campos simples, no para campos de tipo incrustado –

1

Aquí está el truco que encontré en realidad:

https://github.com/symfony/symfony/issues/5906

Usted tiene que escribir un transformador de datos que no hace nada y, a continuación, agregarlo a su campo. Después de eso, juste llamar al método submit() con el segundo parámetro a falso.

Tenga en cuenta que está bien con Symfony 2.3.

2

En caso de que alguien más se encuentre con esta misma pregunta. Prefiero resolverlo personalmente agregando el siguiente atributo dentro de mi plantilla Twig:

{{ form_row(form.<field>, {'required': false}) }} 
+1

No creo que quiera codificarlo en su plantilla. Si desea utilizar el enfoque 'required', use la sugerencia de gilden en su lugar y agréguela al generador de formularios. – Luke

+0

Sí, en la mayoría de las circunstancias creo que sería un mejor enfoque (de ese modo, los requisitos de validación de atributos se propagan a otras plantillas). sin embargo, en algunas situaciones (es decir, aplicaciones simples) colocarlo en una plantilla de Twig no es demasiado terrible :) –

0

El tipo de campo Adivinanza manejar esto. http://symfony.com/doc/current/book/forms.html#field-type-guessing

Es depende de su declaración de forma: "El 'adivinar' se activa cuando se omite el segundo argumento al método add() (o si pasa nula a ella) Si se pasa una matriz de opciones. como tercer argumento (hecho para el día de vencimiento anterior), estas opciones se aplican al campo adivinado ".

2

Si entiendo correctamente, desea la validación del lado del servidor solo si se ingresa el valor. Estoy exactamente en el mismo escenario. Quiero validar una URL solo si se proporciona la URL. La mejor manera que encontré fue escribir mi propia clase de validación personalizada. Puede escribir una clase de validación personalizada genérica.

Seguí este enlace https://symfony-docs-chs.readthedocs.org/en/2.0/cookbook/validation/custom_constraint.html a excepción de algunos cambios debido a la última versión de Symfony. Aquí es la implementación

Acme \ BundleNameBundle \ Validator \ Constraints \ cstmUrl

namespace Acme\BundleNameBundle\Validator\Constraints; 

use Symfony\Component\Validator\Constraint; 
use Symfony\Component\Validator\Constraints\Url; 

/** 
* @Annotation 
*/ 
class CstmUrl extends Url 
{ 
    public $message = 'The URL "%string%" is not valid'; 
} 

Acme \ BundleNameBundle \ Validator \ Constraints \ cstmUrlValidator

namespace Acme\BundleNameBundle\Validator\Constraints; 

use Symfony\Component\Validator\Constraint; 
use Symfony\Component\Validator\Constraints\Url; 
use Symfony\Component\Validator\Constraints\UrlValidator; 

class CstmUrlValidator extends UrlValidator 
{ 
    public function validate($value, Constraint $constraint) 
    { 
     if(!$value || empty($value)) 
      return true; 

     parent::validate($value, $constraint); 
    } 
} 

Validtion.yml

Acme\BundleNameBundle\Entity\Student: 
    Url: 
     - Acme\BundleNameBundle\Validator\Constraints\CstmUrl: ~ 

dentro del controlador simplemente se unen la restricción lo haría normalmente

'constraints'=> new CstmUrl(array("message"=>"Invalid url provided")) 

Estoy seguro de que no puede haber otros mejores maneras de hacerlo, pero por ahora me siento que esto hace bien el trabajo.

Cuestiones relacionadas