你是对的,这个标签(validator.constraint_validator
)由编译器处理 - 从Symfony/FrameworkBundle
传递。 如果你不想使用这个包,但你想链接DI容器和验证器,你应该重新实现这个过程。
首先,我们需要一个ConstraintValidatorFactoryInterface的实例。 Default implementation只是寻找一个类,其名称由validatedBy()方法的约束返回。 Implementation from FrameworkBundle将validatedBy()的结果视为服务标识符/或标签别名,并从容器中获取此服务。我们的实现应该做这样的事情:
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());
}
}
例如,假设我们有一些依赖一些自定义的验证约束和验证器类:
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()
方法的结果。我们通过这个工厂创建与容器相关的验证器服务的实例。所有的约束验证器都以相同的方式注册。
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
不要重新发明轮子。您可以将其配置为仅使用您需要的东西。