Last active
January 3, 2016 10:49
-
-
Save asgrim/8452272 to your computer and use it in GitHub Desktop.
Why doesn't the `ValidatorManager` service get injected into the `ValidatorChain` by default so that validators can easily be configured in module.config.php without having to configure the whole form in there also?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace My\Form; | |
use Zend\Form\Form as ZendForm; | |
use Zend\InputFilter\InputFilterProviderInterface; | |
use Zend\ServiceManager\ServiceLocatorAwareInterface; | |
use Zend\ServiceManager\ServiceLocatorAwareTrait; | |
abstract class AbstractForm | |
extends ZendForm | |
implements ServiceLocatorAwareInterface, InputFilterProviderInterface | |
{ | |
use ServiceLocatorAwareTrait; | |
/** | |
* Override the validator plugin manager to be the global 'validatormanager' | |
* service configured from the service manager, because for some reason it | |
* isn't used by default :/ | |
*/ | |
public function setValidatorManagerToBeGlobalValidatorManager() | |
{ | |
$validatorPluginManager = $this->getServiceLocator()->get('validatormanager'); | |
$formFactory = $this->getFormFactory(); | |
$inputFactory = $formFactory->getInputFilterFactory(); | |
$inputFactory->getDefaultValidatorChain()->setPluginManager($validatorPluginManager); | |
} | |
/** | |
* (non-PHPdoc) | |
* @see \Zend\Form\Form::isValid() | |
*/ | |
public function isValid() | |
{ | |
$this->setValidatorManagerToBeGlobalValidatorManager(); | |
return parent::isValid(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
return array( | |
'validators' => array( | |
'invokables' => array( | |
'My\Validator\Test' => 'My\Validator\Test', | |
), | |
'alias' => array( | |
'Test' => 'My\Validator\Test', | |
), | |
), | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace My\Form\MyForm; | |
use Zend\InputFilter\InputFilterProviderInterface; | |
use Zend\Form\Element; | |
class MyForm extends AbstractForm | |
{ | |
public function __construct($name = null) | |
{ | |
parent::__construct($name); | |
$myField = new Element\Text('myField'); | |
$myField->setLabel('My Field'); | |
$this->add($myField); | |
// Some other fields ... | |
} | |
public function getInputFilterSpecification() | |
{ | |
return array( | |
'myField' => array( | |
'required' => true, | |
'filters' => array( | |
array('name' => 'StripTags'), | |
array('name' => 'StringTrim'), | |
), | |
'validators' => array( | |
array( | |
'name' => 'Test', | |
), | |
), | |
), | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace My\Validator; | |
use Zend\Validator\AbstractValidator; | |
class Test extends AbstractValidator | |
{ | |
const LOL = 'lol'; | |
/** | |
* @var array | |
*/ | |
protected $messageTemplates = array( | |
self::LOL => "Some lols happened", | |
); | |
public function isValid($value) | |
{ | |
$this->error(self::LOL); | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Basically, I want to configure validators from
module.config.php
(so that I can use a factory and inject anything that might be required in the validator).I reported this as a bug in ZF2 some time ago... zendframework/zendframework#4732 , but there does not seem to be built-in way in the framework to use the
ValidatorManager
instance that is in the service manager when using validators, and this is what I have found:On
Zend\InputFilter\Factory#L46
anew ValidatorChain
instance is created. TheZend\Validator\ValidatorChain
class is where the validator plugin manager is used for finding the validators, but if we look atZend\Validator\ValidatorChain#L54
we can see that it always creates a newValidatorPluginManager
instead of using the one that already exists in the Service Manager, so you can never configure it before using it.My solution isn't great - basically, I create an abstract form that overrides the behaviour of the
isValid
function so that it calls my methodsetValidatorManagerToBeGlobalValidatorManager
. This method fetchesValidatorManager
from the Service Manager to start with. It then instantiates the$inputFilterFactory
in exactly the same way asattachInputFilterDefaults
method, but then callssetPluginManager(..)
on the default validator chain. This means now that I can configure services in thevalidators
array key inmodule.config.php
(including factories!) and use them in any form (that inherits myMy/Form/AbstractForm
class).One other thing that MWOP mentioned in the bug report was that the
Zend\Form\FormAbstractServiceFactory
does what I'm expecting (i.e. this means just configuring all the forms inmodule.config.php
). Unfortunately, we do some pretty crazy stuff with our forms which means we need the flexibility of writing our own form classes, so this route is a no-go. However, I can see at the bottom ofZend\Form\FormAbstractServiceFactory::marshalInputFilter()
method, it is doing:which is exactly the same way as my solution works... but this seems really long-winded...
TL;DR
So basically... why doesn't the
ValidatorManager
service get injected into theValidatorChain
by default so that validators can easily be configured inmodule.config.php
without having to configure the whole form in there also?