本文介绍了如何使用Symfony组件配置对自定义验证器的依赖关系?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在项目中使用了 Symfony验证程序 Symfony服务容器,但没有使用完整的Symfony框架.

I am using Symfony Validator and Symfony Service Container in a project, but not the full Symfony Framework.

我编写了一个自定义验证器,该验证器需要一些依赖项作为构造函数参数来提供.

I have written a custom validator that requires some dependencies to be supplied as constructor arguments.

Symfony文档描述了将验证程序配置为服务的方法,已成功完成.但这便说明了使用 validator.constraint_validator 服务标签的重要性,我怀疑这会将它们粘合在一起.

The Symfony Documentation describes a method of configuring the validator as service, which I have done successfully. But then it makes of point of using the validator.constraint_validator service tag, which I suspect glues them together.

此服务标签似乎特定于使用完整的Symfony Framework时-当我添加此标签时,Symfony Validator不会神奇地加载我的自定义验证器(毫不奇怪).

This service tag seems to be specific to when using the full Symfony Framework -- Symfony Validator is not magically loading my custom validator when I add this tag (unsurprisingly.)

那么,如何链接验证器和服务容器组件?还是有其他让Symfony Validator为我的客户验证器加载依赖项的策略?

So, how can I link the Validator and Service Container components? Or is there any other strategy for having Symfony Validator to load my customer validator with dependencies?

推荐答案

是的,此标记( validator.constraint_validator )由 Symfony/FrameworkBundle .如果您不想使用此捆绑包,但想将DI容器与验证器链接,则应重新实现此过程.

You are right, this tag (validator.constraint_validator) processed by compiler-pass from Symfony/FrameworkBundle. If you don't want to use this bundle, but you want to link DI container with validator, you should re-implement this process.

首先,我们需要一个ConstraintValidatorFactoryInterface实例.默认实现只是寻找一个类,其名称由validatedBy()约束方法. FrameworkBundle的实现将validatedBy()的结果视为服务标识符/或标签别名,并从容器中获取此服务.我们的实现应执行以下操作:

First, we need an instance of ConstraintValidatorFactoryInterface. Default implementation just looks for a class, with name returned by validatedBy() method of constraint. Implementation from FrameworkBundle considers result of validatedBy() as service identifier/or tag alias and gets this service from container. Our implementation should do something like that:

use Symfony\Component\DependencyInjection\ContainerInterface;

use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
use Symfony\Component\Validator\Constraint;

class ContainerConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
{
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function getInstance(Constraint $constraint)
    {
        // Simplified implementation, just for example:
        return $this->container->get($constraint->validatedBy());
    }
}

例如,假设我们有一些自定义验证约束和具有某些依赖项的验证器类:

For example, suppose we have some custom validation constraint and validator class with some dependency:

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class CustomConstraint extends Constraint
{
    public $message = 'Oops!';

    public function validatedBy()
    {
        return 'validator.custom';
    }
}

class CustomConstraintValidator extends ConstraintValidator
{
    private $dependency;

    public function __construct($dependency)
    {
        $this->dependency = $dependency;
    }

    public function validate($value, Constraint $constraint)
    {
        if (rand() % 2 === 0) {
            $this->context
                ->buildViolation($constraint->message)
                ->addViolation();
        }
    }
}

接下来,我们将约束验证器作为服务注册,其ID与相关约束对象中 validatedBy()方法的结果相同.我们通过该工厂创建与容器相关的验证器服务的实例.所有以相同方式注册的约束验证器都将可用.

Next we register constraint validator as service with ID same as result of validatedBy() method from related constraint object. We create instance of the validator service related with container through this factory. All constraints validators, registered as same manner will be available.

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

$container = new ContainerBuilder();
$container->register(
    'validator.custom', 
    new CustomConstraintValidator('Some dependency value')
);

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

$violations = $validator->validate('test value', [ 
    new CustomConstraint() 
]);

它可以工作,但是我建议考虑使用 FrameworkBundle 来避免重新发明轮子.您可以将其配置为仅使用所需的东西.

It works, however I recommend to consider of using FrameworkBundle to not reinvent the wheel. You can configure it to use only things that you need.

这篇关于如何使用Symfony组件配置对自定义验证器的依赖关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-13 14:02