zf2 / zf3注册自定义验证器并将其注入fieldset

时间:2017-09-29 22:07:35

标签: php zend-framework2 zend-framework3

我有一个自定义验证器:

class CustomValidator extends RecordExists
{    
    public function isValid($value, array $context = null)
    {
        // some behaviour
        return parent::isValid($value);
    }
}

此验证器有一个工厂:

class CustomValidatorFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $validator = new CustomValidator();
        // preparations for CustomValidator
        return $validator;
    }
}

CustomValidator及其工厂已在module.config.php下注册

'validators' => [
    'factories' => [
        CustomValidator::class => CustomValidatorFactory::class,
    ],
], 

CustomValidator附加到getInputFilterSpecification()中的字段集输入

'validators' => [
    ['name' => CustomValidator::class],
]

通过表单的init()方法调用字段集,并在控制器工厂中将表单调用为$container->get('FormElementManager')->get('TheNeededForm')

问题在于,出于某种原因,CustomValidator不是通过CustomValidatorFactory实例化,而是getInputFilterSpecification()字段集只创建new CustomValidator()的实例。

如何通过工厂进行自定义验证器实例化?

PS:我已经上网了,发现了类似的问题,但是那里给出的解决方案没有帮助:它建议在'abstract_factories' => [FormAbstractServiceFactory::class]指令下的module.config.php中添加'form_elements'

1 个答案:

答案 0 :(得分:0)

我已经在这里回答了这个问题

https://stackoverflow.com/a/61287283/4685379

这里是:

在ZF3 / Laminas中,如果将验证器注册为可调用项,则可以使用表格的getInputFilterSpecification()调用验证器,这没有问题。如果使用工厂实例化验证器,则会遇到麻烦。如果我理解正确,即使您的表格是这样注册的

'form_elements' => [
    'factories' => [
        SomeForm::class => SomeFormFactory::class,
    ]
]

和您的验证者:

'validators' => [
    'factories' => [
        SomeValidator::class => SomeValidatorFactory::class,
    ]    
]

您将不会通过工厂实例化验证器。原因是表单工厂(您得到的$form->getFormFactory()之类的表单工厂)具有输入过滤器工厂,并且其中存在默认验证程序链。并且此验证程序链没有附加ValidatorManager。并且如果没有ValidatorManager,则默认链无法将验证者名称映射到验证者工厂。

要解决所有这些头痛问题,请在您的控制器工厂中执行以下操作:

$form->('FormElementManager')->get(SomeForm::class);
$form->getFormFactory()->getInputFilterFactory()
    ->getDefaultValidatorChain()->setPluginManager($container->get('ValidatorManager'));

麻烦就过去了。