如何将实例传递给 symfony 表单验证器类? [英] How to pass an instance to symfony form validator class?

查看:20
本文介绍了如何将实例传递给 symfony 表单验证器类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建自定义 symfony 表单验证器约束.我创建了两个类,一个约束和一个验证器,它工作正常.但是我需要将doctrine entitymanager 实例传递给验证器类,因为我使用它们是独立的而不是框架,我没有 yaml 配置文件.我在验证器类中创建了一个构造函数来拥有 $em,而在控制器中我有:

I am trying to create a custom symfony form validator constraint. I created two class, one constraint and one validator and it works fine. But I need to pass doctrine entitymanager instance to validator class, as I am using them standalone and not framework, I don't have yaml configuration file. I created a constructor in validator class to have $em, and in controller I have:

->add('email', EmailType::class, [                                              
    'constraints' => [
        new Assert\Email(['message' => 'invalid.email', 'mode' => 'strict', 'normalizer' => 'trim']),
        new Assert\EmailExists($em),
    ],
 ]);

但是在我的验证器类中我没有得到 $em,我该怎么办?我还尝试在主约束类中使用构造函数,然后在验证器中使用 parent::construct(),但仍然无法正常工作.

But I am not getting $em, in my validator class, what should I do? I also tried to have constructor in main constraint class, then in validator I had parent::construct(), still not working.

我也读过这个如何配置依赖项在带有 Symfony 组件的自定义验证器上? 但我没有创建工厂类,而是使用了当前的因子类并使用了这个:

I did read this too How to configure dependencies on custom validator with Symfony Components? but instead of making the factory class, I used the current factor class and used this:

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Validator\ContainerConstraintValidatorFactory;

$container = new ContainerBuilder();
$container
    ->register('customEmailUniqueEntity', 'EmailExistsValidator')
    ->addArgument($em);
$validatorBuilder = Validation::createValidatorBuilder();
$validatorBuilder->setConstraintValidatorFactory(
    new ContainerConstraintValidatorFactory($container)
);

$validator = $validatorBuilder->getValidator();
$violations = $validator->validate('email address', [ 
    new EmailExists() 
]);

if (0 !== count($violations)) {
    // there are errors, now you can show them
    foreach ($violations as $violation) {
        echo $violation->getMessage().'<br>';
    }
}

使用此代码,依赖项注入和验证都可以正常工作,但是有没有技巧可以将此自定义约束作为表单构建器中的约束"数组参数而不是手动验证?

With this code both dependency injection and validation works fine, but is there a trick to have this custom constraint as 'constraint' array argument within form builder rather than validating it manually?

->add('email', EmailType::class, [                                              
    'constraints' => [
        new Assert\Email(['message' => 'invalid.email', 'mode' => 'strict', 'normalizer' => 'trim']),
        new Assert\EmailExists($em),
    ],
 ]);

使用上面的代码,我无法将 $em 传递给我的自定义验证器的构造函数.有什么技巧吗?

With code above I cannot pass $em to the constructor of my custom Validator. Any trick possible?

为了注入学说 EntityManager,在 EmailExists 类中我有:

In order to inject doctrine EntityManager, in EmailExists class I had:

 public function validatedBy()
 {
        return 'customEmailUniqueEntity';
        //return \get_class($this).'Validator';
 }

然后我有:

$container = new ContainerBuilder();
$container
    ->register('customEmailUniqueEntity', 'EmailExistsValidator')
    ->addArgument($em);

因为如果我从 validatedBy() 返回验证器类,我无法将 $em 注入验证器的构造函数.我用下面的答案:

because if I was returning validator class from validatedBy() I could not inject $em to the constructor of validator. With the answer below I used:

->addTag('validator.constraint_validator');

但是现在我收到 customEmailUniqueEntity class not found 错误,好像我从 validatedBy() 返回验证器一样,注入不起作用,我该怎么办?我试图返回

But now I am getting customEmailUniqueEntity class not found error, as if I return validator from validatedBy(), injection will not work, what should I do? I tried to return

 public function validatedBy()
 {
        return 'EmailExists';
        //return \get_class($this).'Validator';
 }

但是这个,当然我收到了 initialize() 错误.请指教.

but this one, of course I am getting initialize() error. Please advise.

编辑 2:

我添加了 addTag 到:

I added addTag to:

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Validator\ContainerConstraintValidatorFactory;

$container = new ContainerBuilder();
$container
    ->register('customEmailUniqueEntity', 'EmailExistsValidator')
    ->addArgument($em),
    ->addTag('validator.constraint_validator');

$validatorBuilder = Validation::createValidatorBuilder();
$validatorBuilder->setConstraintValidatorFactory(
    new ContainerConstraintValidatorFactory($container)
);

$validator = $validatorBuilder->getValidator();
$violations = $validator->validate('email address', [ 
    new EmailExists() 
]);

if (0 !== count($violations)) {
    // there are errors, now you can show them
    foreach ($violations as $violation) {
        echo $violation->getMessage().'<br>';
    }
}

在 EmailExistsValidator 的构造函数中我有:

and in constructor of EmailExistsValidator I have:

var_dump($em);

并且我在验证器中获得了 $em 对象,因此注入了 $em 并且添加 addTag() 不会导致任何错误.如果我删除 EmailExists 约束的 validatedBy(),则不会进行注入.在那种方法中我正在做

and I got $em object in validator, so $em is injected and adding addTag() did not cause any error. If I remove validatedBy() of EmailExists contsraint, injection will not be done. In that method I am doing

return `customEmailUniqueEntity;`

因为如果我返回EmailExistsValidator,则不会进行注入.现在如何使用 validator.constraint_validatorEmailExists() 作为表单的约束数组参数?如果我使用 new EmailExists() 我会得到两个验证器类的参数,因为 $em 不会以这种方式注入.怎么办?

because if I return EmailExistsValidator, injection will not be done. Now how to use validator.constraint_validator or EmailExists() as constraints array param of the form? if I use new EmailExists() I will get Two Few Aguments for validator class as $em wll not be injected this way. What to do?

推荐答案

ContainerConstraintValidatorFactory 在确定实际验证器时,永远不会考虑您的 customEmailUniqueEntity 服务用于 EmailExists 约束.

Your customEmailUniqueEntity service will never be taken into account by the ContainerConstraintValidatorFactory when it determines the actual validator to be used for the EmailExists constraint.

为了让工厂知道哪些服务是约束验证器,您需要使用 validator.constraint_validator 标记来标记它,如下所示:

In order to let the factory know which services are constraint validators you need to tag it with the validator.constraint_validator tag like this:

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;

$container = new ContainerBuilder();
$container
    ->register('customEmailUniqueEntity', 'EmailExistsValidator')
    ->addArgument($em)
    ->addTag('validator.constraint_validator');
$container->addCompilerPass(new AddConstraintValidatorPass());
$container->compile();

这篇关于如何将实例传递给 symfony 表单验证器类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆