Welcome to Abdul Malik Ikhsan's Blog

Zend Framework 2 : Utilize ValidatorManager to work with Custom Validator in Zend\Form

Posted in Tutorial PHP, Zend Framework 2 by samsonasik on February 2, 2014

zf2-zendframework2ValidatorManager 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 :
form-validator-custom
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.
danizord-suggestion-on-getInputFilterSpecification

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

About these ads

5 Responses

Subscribe to comments with RSS.

  1. Isaac said, on February 5, 2014 at 2:02 am

    Thanks Again.

  2. Dara said, on March 1, 2014 at 12:33 am

    Hello Sir

    i am using language translations in zend 2 learning project when i am using

    $this->add(array(
    ‘name’ => “username”,
    ‘type’ => ‘Zend\Form\Element\Text’,
    ‘options’ => array(
    ‘label’ => _(‘Your Username’), // i found fatal error at this position
    ),
    ));

    fatal error : Call to undefined function Incuser\Form\_()

    _() for translate a form label give me fatal error
    i am using php 5.3.1 right now .

    Please help me , i am unable to figure out this issue.

    • samsonasik said, on March 1, 2014 at 8:11 am

      check you typing :P, string "_" in php must be in '' or ""

      • Dara said, on March 2, 2014 at 11:43 pm

        Thanks Sir for reply on my question

        php fatal error i found on

        ‘label’ => _(‘Your Username’), and when am using

        ‘label’ => ‘Your Username’

        this is working fine

        i am using _() for translation in zend 2. is i am missing any class for this?

  3. SimonC said, on July 18, 2014 at 3:53 pm

    Hi, if want to access my database in the validator. What is the way to go? I tried it via Service Manager but i get this error message “Argument 1 passed to Test\Model\TestTable::__construct() must be an instance of Zend\Db\TableGateway\TableGateway”. Best regards


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 239 other followers

%d bloggers like this: