Zend Framework 2 : Utilize ValidatorManager to work with Custom Validator in Zend\Form
ValidatorManager is a Plugin Manager that corresponding to Zend\Validator\ValidatorPluginManager, and used to manage validator instances. While we work with existing validators in Zend\Form, we can call validators in ‘validators’ key under inputFilter specification with the ‘invokables’ registered service at
Zend\Validator\ValidatorPluginManager
. In this post, I will propose detail way to work with custom validator.
For example, we have custom validator named Special
to handle words with at least one special character in it, so the form when not valid will show like this :
So, we need to start with creating the validator like the following :
//filename : module/TutorialValidator/src/TutorialValidator/Validator/Special.php namespace TutorialValidator\Validator; use Zend\Validator\AbstractValidator; class Special extends AbstractValidator { const NOTSPECIAL = 'NOTSPECIAL'; protected $messageTemplates = array( self::NOTSPECIAL => 'Value should at least one special character', ); public function __construct(array $options = array()) { parent::__construct($options); } public function isValid($value) { $this->setValue($value); $special = preg_match('#[\W]{1,}#', $value); if (!$special) { $this->error(self::NOTSPECIAL); return false; } return true; } }
And we need to use it to validate the forms, so we need to register the validator in ‘validators’ key in our configuration:
//filename : module/TutorialValidator/config/module.config.php 'validators' => array( 'invokables' => array( 'Special' => 'TutorialValidator\Validator\Special' ), ),
There are two ways to build form with custom validator.
A. We can use Zend\Form\FormAbstractServiceFactory
that can be configured via ‘forms’ key in configuration files.
To do this, we need to :
1. register Zend\Form\FormAbstractServiceFactory
into configuration
//filename : module/TutorialValidator/config/module.config.php 'service_manager' => array( //other service registration here... 'abstract_factories' => array( 'Zend\Form\FormAbstractServiceFactory', ), //other service registration here... ),
2. And then, configure the ‘forms’
//filename : module/TutorialValidator/config/module.config.php 'forms' => array( 'SampleForm' => array( 'hydrator' => 'ObjectProperty', 'type' => 'Zend\Form\Form', 'elements' => array( array( 'spec' => array( 'type' => 'Text', 'name' => 'sampleinput', 'options' => array( 'label' => 'Sample Input:', ) ), ), array( 'spec' => array( 'type' => 'Submit', 'name' => 'submit', 'attributes' => array( 'value' => 'Go', ) ), ), ), 'input_filter' => array( 'sampleinput' => array( 'required' => true, 'validators' => array( array( 'name' => 'Special', ), ), ), ), ), ),
SampleForm
is a registered form service that can be called via ‘FormElementManager’ manager. Special
is a custom validator that registered at ‘validators’ key or getValidatorConfig() under Module class.
B. Using form class
For form class, we need to implements Zend\InputFilter\InputFilterProviderInterface
and implement method getInputFilterSpecification
:
To do this, we need to :
1. create the form class
//filename : module/TutorialValidator/src/TutorialValidator/Form/SampleForm.php namespace TutorialValidator\Form; use Zend\Form\Form; use Zend\InputFilter\InputFilterProviderInterface; class SampleForm extends Form implements InputFilterProviderInterface { public function init() { $this->add(array( 'name' => 'sampleinput', 'type' => 'Text', 'options' => array( 'label' => 'Sample Input: ', ), )); $this->add(array( 'name' => 'submit', 'attributes' => array( 'type' => 'submit', 'value' => 'Go', 'id' => 'submitbutton', ), )); } public function getInputFilterSpecification() { return array( array( 'name' => 'sampleinput', 'required' => true, 'validators' => array( array('name' => 'Special'), ), ), ); } }
2. Register form service in ‘form_elements’ key in config
//filename : module/TutorialValidator/config/module.config.php 'form_elements' => array( 'invokables' => array( 'SampleForm' => 'TutorialValidator\Form\SampleForm' ), ),
When everything is OK, we can call the form via ‘FormElementManager’ in controller ( you can inject controller with SampleForm service via ‘factories’ key of course :)) :
public function indexAction() { $form = $this->getServiceLocator() ->get('FormElementManager') ->get('SampleForm'); $request = $this->getRequest(); if ($request->isPost()) { $form->setData($request->getPost()); if ($form->isValid()) { echo 'Great!form is valid'; } } $viewmodel = new ViewModel; $viewmodel->setVariable('form', $form); return $viewmodel; }
Done. I’ve uploaded the sample code to my github account : https://github.com/samsonasik/TutorialValidator . Hope it helpful 😉
Note : Thanks to Daniel Gimenes for the suggestion to this post and make a PR to my repository on github.
References :
1. http://zf2.readthedocs.org/en/latest/modules/zend.mvc.services.html
2. http://stackoverflow.com/questions/19642139/possible-to-create-a-factory-to-instantiate-custom-form-validators
3. http://stackoverflow.com/questions/13476164/zend-framework-2-custom-validators-for-forms
4. https://github.com/samsonasik/TutorialValidator/pull/1
9 comments