Custom Validators in Zend Form

Adding a custom form field validator to a Zend_Form is extremely simple. Here’s my attempt at breaking it down for you.

The basic code of a Zend Form validator looks like this (this example performs a custom validation on an email field to ensure that it is unique in the ‘user’ table)

class My_UniqueEmail extends Zend_Validate_Abstract
{
    const EMAIL_EXISTS='';
    protected $_messageTemplates = array(
        self::EMAIL_EXISTS=>'Email "%value%" exists'
    );
    public function __construct(Model_User $model)
    {
        $this->_model = $model;
    }
    public function isValid($value, $context=null)
    {
        $this->_setValue($value);
        //insert logic to check here...
        if (!error)
            return true;

        $this->_error(self::EMAIL_EXISTS); 
        return false;
    }
}

The basic rules are:

  1. Custom validators must inherit from Zend_Validate_Abstract
  2. Use  $_messageTemplates to build your custom error message (to be displayed in case of failure). Note that %value% is replaced by the field being validated.
  3. Use the constructor to pass parameters as required – Here, we pass in the user model.. we can then check for duplicate emails in the table.
  4. All validators must implement the isValid() method. The framework automatically passes the value of the field being validated as the first parameter, and the entire form array as the second parameter ($context) . Returning ‘true’ signals that the validation was ok. If not, set the error message (_error) and return false.

Now that we have the basic validator syntax out of the way, let us get down to how the routine can actually be inserted into the runtime.

There are two methods that you can use for this:

  1. Using the ‘addElementPrefixPath’ method of the form
class Form_User extends Zend_Form
{
    public function init()
    {
        $this->addElementPrefixPath(
                'My',
                APPLICATION_PATH.'/forms/validate/',
                'validate'
        );

...
...

}
}

The addElementPrefixPath method considers custom validators as ‘plugins’ and loads them. The first parameter is the namespace, the second is the actual directory location of the plugin and the third parameter is the type (can be validate, filter or decorator)

When the addElementPrefixPath method is used, the following syntax should be used to load the validator:

.......

$email = $this->createElement('text', 'email');
$email->setLabel('Email');
$email->setRequired(true);

$email->addValidator('UniqueEmail',false, array(new Model_User()));

.....

Note that the addValidator call uses the ‘Non-Namespaced’ name of the validator class.. The default plugin loader automatically adds the prefix (1st parameter)  specified in the addElementPrefixPath function before making the call.

2. The second method of including custom validators is using what I call the “plain old object instantiation” method

This is my preferred method for custom validation. For some reason, most books and online material discuss the addElementPrefixPath method while ignoring the more commonsense direct approach. Here is how you can employ this to load your custom validators:

Step1 :

Create your validation routine so that can be autoloaded by the framework.. For instance, if you have automatic module resource loading setup, I would put the following class UniqueEmail.php in the directory /forms/validate/

class Form_Validate_UniqueEmail extends Zend_Validate_Abstract
{
    const EMAIL_EXISTS='';
    protected $_messageTemplates = array(
        self::EMAIL_EXISTS=>'Email "%value%" exists'
    );
    public function __construct(Model_User $model)
    {
        $this->_model = $model;
    }
    public function isValid($value, $context=null)
    {
        $this->_setValue($value);
        //insert logic to check here...
        if (!error)
            return true;

        $this->_error(self::EMAIL_EXISTS); 
        return false;
    }
}

Step 2:

In your specialized form class, pass an instance of the validator to the addValidator method like so:

.......

$email = $this->createElement('text', 'email');
$email->setLabel('Email');
$email->setRequired(true);

$email->addValidator(new Form_Validate_UniqueEmail(new Model_User()));

.....

That’s all there to it! the UniqueEmail class is loaded like any other class and the field is validated.

Advertisements

7 thoughts on “Custom Validators in Zend Form

  1. How to custom validate (I want to add custom error messages )
    Six combo boxes(Zend_Form_Element_Select) which contain from date / toDate values.
    The Date Range rules in UI will be as below
    1)The from date cannot be more than 45 days in the past
    2)The date range between from and to date cannot exceed more than 30 days

    Please help
    Regards
    Sajad

  2. Hi,
    I did follow your code, but it always dispay “Email ‘myemail@email.com’ exist”. What’s wrong? Can you help me?

    1. Hi,

      If you do NOT return “true” from the isvalid() function, the error message will be displayed.
      The main part is the logic that goes into the following lines.. you need to do your custom check and set $error to true

      //insert logic to check here…
      15 if (!$error)
      16 return true;

      Hope this helps!

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