2011-09-22 66 views
21

我想仅在值不为空时才将验证器应用于对象属性。如何在symfony2验证器中允许空值

现在的标准symfony的行为:如果邮件是空,或空字符串

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

该对象将无法通过验证,有没有办法告诉验证断言为有效,空值,仅当字段有数据时才验证?

PS我知道我可以编写回调验证器,但为每个字段写回调只是为了让“allowEmpty”功能不太好。

回答

22

对于所有可选字段,您必须在FormBuilder类中明确设置'required' => false。这里有一段描述field type options


编辑。获得不少赞扬。默认全部验证器对待null值为有效,除了NotNullNotEmpty。这两个问题都没有用到。隐含的问题是关于如何关闭默认打开的客户端required属性。

+26

这不是正确的答案。 'required'选项只强制执行客户端验证。 – TyrionLannister

+7

@TyrionLannister你确实是对的。但是,除了具有NotNull()和NotEmpty()约束之外,没有一个默认验证器会导致空值被视为无效。看到提问者既没有这些约束,也隐含了问题出在客户端的HTML5'required'属性上。 – gilden

+3

@gilden与所有应有的尊重,'required'属性与空值被批准没有任何共同之处。它只用于HTML5客户端验证,并且与验证(服务器端验证)无关。 –

19

设置required选项不是解决办法:

还要注意的是所需要的选项设置为true不会导致服务器端验证得到应用。换句话说,如果用户为该字段提交空白值(例如,使用旧浏览器或Web服务),除非使用Symfony的NotBlank或NotNull验证约束,否则它将被接受为有效值。

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

对于我的自定义验证,我添加了一个

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

isValid()方法。但是,我不确定什么是标准验证器类的最佳方式。

+1

这应该是被接受的答案,因为接受的答案只适用于简单字段而不适用于嵌入类型字段 –

1

这里是我居然找到了窍门:

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

你需要编写一个数据转换,什么也不做,然后把它添加到你的领域。 然后,将第二个参数的submit()方法调用为false。

请注意,Symfony 2.3可以。

2

只是为了防止其他人遇到同样的问题。我更喜欢亲自解决它,在我的树枝模板内添加以下属性:

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

我不认为您想要在模板中对其进行硬编码。如果你想使用'required'方法,请改用gilden的建议并将其添加到表单构建器中。 – Luke

+0

是的,在大多数情况下,我认为这会是一种更好的方法(通过这种方式属性验证需求在其他模板中传播),然而在某些情况下(即简单的应用程序)将其放入树枝模板并不太可怕:) –

0

字段类型猜测处理此。 http://symfony.com/doc/current/book/forms.html#field-type-guessing

这取决于你的窗体声明:“在‘猜测’当你忽略第二个参数add()方法被激活(或者,如果你传递null的话)如果你传递一个选项数组。作为第三个参数(针对上面的dueDate完成),这些选项将应用于猜测字段。“

2

如果我理解正确,只有在输入值时才需要服务器端验证。我完全一样。我只想在URL提供的情况下验证URL。我碰到的最好的方法是写我自己的自定义验证类。你可以编写一个通用的自定义验证类。

我跟着这个链接https://symfony-docs-chs.readthedocs.org/en/2.0/cookbook/validation/custom_constraint.html除了因为symfony的最新版本的一些变化。 这里是实现

的Acme \ BundleNameBundle \验证\约束\ 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 \验证\约束\ 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: ~ 

内部控制只是绑定约束,你通常会做

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

我相信可以有其他更好的做这件事的方式,但现在我觉得这样做的工作做好。