Symfony 验证 - 在自定义验证行为中设置属性路径

Posted

技术标签:

【中文标题】Symfony 验证 - 在自定义验证行为中设置属性路径【英文标题】:Symfony validation - set the property path in custom validation act 【发布时间】:2021-04-09 04:08:42 【问题描述】:

我想问一下,如何在违反约束时设置属性路径。

到目前为止,我正在做一个普通的验证,比如(用户是一个普通的实体,有一些预定义的约束——它们按方面工作):

$validationErrors = $this->validator->validate($user);

接下来,在用户注册控制器方法中,我正在尝试手动方法(因为将约束直接放在用户实体中会导致每次都验证密码)

我在需要时验证密码,如下所示:

$passwordLength = mb_strlen($password);
$passwordMinLength = new Assert\Length(null, 8);
$passwordErrors = $this->validator->validate($passwordLength, [ $passwordMinLength ]);

然后,我将结果添加到现有集合中:

$validationErrors->addAll($passwordErrors);

但是当我检查密码产生的违规时,没有在其上定义 propertyPath。我构建了一个自定义树枝扩展,它依赖于设置的属性路径。我如何告诉它在 $passwordErrors 数组上使用名为“密码”的 propertyPath?

希望你能理解我的问题:)。

最好的问候!

罗伯

编辑: 我找到了适合我的解决方法。我敢肯定,这不是解决我的问题的最佳方式,但由于我已经为这件小事浪费了几个小时,我决定宁愿选择解决方法,而不是在这件小事上花更多时间。

我的解决方法 虽然我无法访问私有属性propertyPath,但我想为每个违规设置propertyPath,我通过以下方式解决了它:

一开始我创建了一个闭包函数:

$closure = Closure::bind(function (ConstraintViolation $violation) 
    $violation->propertyPath = 'password';
, null, ConstraintViolation::class);

然后我为每次违规调用它:

foreach ($passwordErrors as $violation) 
    // $violation->propertyPath = 'password';
    $closure($violation);

【问题讨论】:

【参考方案1】:

如果我理解正确,您需要一个类约束验证器。 您需要将此添加到约束类:

public function getTargets()

    return self::CLASS_CONSTRAINT;

因此,验证器的validate() 方法获取一个对象作为其第一个参数,atPath() 方法用于定义与验证错误关联的属性。

class ProtocolClassValidator extends ConstraintValidator

    public function validate($protocol, Constraint $constraint)
    
        if ($protocol->getFoo() != $protocol->getBar()) 
            $this->context->buildViolation($constraint->message)
                ->atPath('foo')
                ->addViolation();
        
    

文档:https://symfony.com/doc/current/validation/custom_constraint.html

【讨论】:

【参考方案2】:

我刚刚发现了如何修改现有的违规行为 而不是使用

$validationErrors->addAll($passwordErrors);

在您的自定义验证器中,使用此

/** @var ConstraintViolationInterface $violation */
foreach ($validationErrors as $violation) 
    $this->context->buildViolation($violation->getMessage())
        ->atPath('password')
        ->addViolation();

【讨论】:

以上是关于Symfony 验证 - 在自定义验证行为中设置属性路径的主要内容,如果未能解决你的问题,请参考以下文章

在自定义验证器中使用标准验证器进行 Grails 验证

Symfony2 测试中的伪造身份验证 - 控制器上的 get('security.context')->getToken() 返回的令牌与 TestCase 中设置的令牌不同

Laravel - 在自定义验证中使用验证规则

为啥在自定义身份验证和登录模块中使用克隆?

Symfony2 自定义身份验证:用户登录但未通过身份验证

在 symfony 2 中将验证组设置为嵌入表单