如何在 symfony2 验证器中允许空值

Posted

技术标签:

【中文标题】如何在 symfony2 验证器中允许空值【英文标题】:How to allow empty values in symfony2 validators 【发布时间】:2011-11-23 01:39:59 【问题描述】:

我想仅在值不为空时对对象属性应用验证器。

现在标准的 symfony 行为:

class Entity

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

如果电子邮件为 null 或空字符串,该对象将不会通过验证,有没有办法告诉验证器断言为有效的空值,并且仅在字段有数据时验证?

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

【问题讨论】:

【参考方案1】:

您必须在 FormBuilder 类中为所有可选字段显式设置 'required' => false。这是一段描述field type options的段落。


编辑。获得不少反对票。默认情况下,所有验证器将 null 值视为有效,除了 NotNullNotEmpty。两个都没有在问题中使用。问题隐含地是关于如何关闭默认打开的客户端required 属性。

【讨论】:

这不是正确的答案。 'required' 选项仅强制执行客户端验证。 @TyrionLannister 你确实是正确的。但是,除了具有NotNull()NotEmpty() 约束时,所有默认验证器都不会导致空值被视为无效。鉴于提问者没有这些限制,暗示问题出在客户端 html5 required 属性上。 @gilden 恕我直言,required 属性与批准的空值没有任何共同之处。它仅用于 HTML5 客户端验证,与验证(服务器端)完全无关。 @AndrzejOśmiałowski 绝对,请查看您上面的评论。这正是我所说的:) 如果他根本不知道实现它的正确方法是设置 NotNull 或 NotEmpty 约束怎么办?我发现这个解释很有趣。即便如此,我相信他会后悔当他尝试通过 XHR 发送带有 JSON 格式数据的表单数据时犯了多少错误,表单将被传递,您将一无所获。这正是我现在所面临的。这只是一定程度上的答案,而不是完整的答案。【参考方案2】:

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

我关注了这个链接https://symfony-docs-chs.readthedocs.org/en/2.0/cookbook/validation/custom_constraint.html,除了因为 symfony 的最新版本而做了一些更改。 这是实现

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: ~

在 Controller 中只绑定你通常会做的约束

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

我相信还有其他更好的方法可以做到这一点,但现在我觉得这做得很好。

【讨论】:

【参考方案3】:

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

这取决于您的表单声明:“当您省略 add() 方法的第二个参数(或者如果您将 null 传递给它)时,“猜测”将被激活。如果您传递一个options 数组作为第三个参数(为上面的 dueDate 完成),这些选项将应用于猜测的字段。"

【讨论】:

【参考方案4】:

以防万一其他人遇到同样的问题。我更喜欢通过在我的 Twig 模板中添加以下属性来亲自解决它:

 form_row(form.<field>, 'required': false) 

【讨论】:

我认为您不想在模板中硬编码。如果您想使用 required 方法,请改用 gilden 的建议并将其添加到表单构建器中...... 是的,在大多数情况下,我认为这将是一种更好的方法(这样属性验证要求会在其他模板中传播),但是在某些情况下(即简单的应用程序)将其放入 Twig 模板中并不是太可怕了:)【参考方案5】:

这是我实际发现的技巧:

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

您需要编写一个什么都不做的数据转换器,然后将其添加到您的字段中。 之后,只需调用 submit() 方法,并将第二个参数设置为 false。

请注意,Symfony 2.3 没问题。

【讨论】:

【参考方案6】:

设置required 选项不是解决方案:

另请注意,将 required 选项设置为 true 不会导致应用服务器端验证。换句话说,如果用户为该字段提交了一个空白值(例如,使用旧的浏览器或 Web 服务),它将被接受为有效值,除非您使用 Symfony 的 NotBlank 或 NotNull 验证约束。

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

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

if (null == $value) 
    return true;

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

【讨论】:

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

以上是关于如何在 symfony2 验证器中允许空值的主要内容,如果未能解决你的问题,请参考以下文章

JOI:允许数组中的空值

Symfony2 - 如何验证控制器中的电子邮件地址

在 Core 之外使用 Symfony2 验证器注解

在正则表达式电子邮件中允许 + 验证电子邮件 [重复]

Symfony2:如何使用非默认实体管理器对用户进行身份验证?

SQL语句如何写不等于?