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

62lalag4  于 2023-03-30  发布在  其他
关注(0)|答案(3)|浏览(104)

我想问一下,如何设置属性路径对约束的违反。
到目前为止,我正在做一个普通的验证,比如(其中user是一个带有一些预定义约束的普通实体-这些约束作为aspected工作):

$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。我构建了一个自定义的twig扩展,它依赖于设置的propertyPath。我如何告诉它在$passwordErrors数组上使用名为'password'的propertyPath?
希望你能理解我的问题:)
最好的问候!
罗伯

编辑:我找到了适合我的工作解决方案.我敢肯定,这不是解决我的问题的最佳方式,但因为我已经浪费了几个小时的这个小东西,我决定宁愿选择变通而不是工作更多的时间在这个小东西.
我的解决方案因为我想在无法访问私有属性
propertyPath
的情况下,为每个违规设置propertyPath,所以我采用了以下方法解决:

首先,我创建了一个闭包函数:

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

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

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

iibxawm41#

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

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

g52tjvyc

g52tjvyc2#

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

$validationErrors->addAll($passwordErrors);

在您的自定义验证程序中,使用

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

kzmpq1sx3#

如果我使用标准约束,那么我使用这种方法:

public function setViolationsPath(
    ConstraintViolationListInterface $violations,
    string $pathName
): void {
    $path = new ReflectionProperty(ConstraintViolation::class, 'propertyPath');
    $path->setAccessible(true);

    foreach ($violations as $violation) {
        $path->setValue($violation, $pathName);
    }
}

相关问题