Home > Zend_Validate > Creating Fields Comparison Validator for Zend_Form

Creating Fields Comparison Validator for Zend_Form

intro
This article illustrates how to create a custom validator to compare values of elements of Zend_Form. You can download the source code of this article from here.

1.Create Validator
The validator of the following specifications is made.

parameter description
$key String value to identify which fields are compared.
$operator Operator to compare the fields.
The operator is not specified in the element in the comparison destination.
Error Message Key Initial Error Message
fieldNotSame '%value%' is not equal to '%key_value%'
fieldNotGreaterThan '%value%' is not greater than '%key_value%'
fieldNotGreaterThanEqual '%value%' is not greater than or equal to '%key_value%'
fieldNotLessThan '%value%' is not less than '%key_value%'
fieldNotLessThanEqual '%value%' is not less than or equal to '%key_value%'

Create the file library/My/Validate/FieldCompare.php with the following content.

<?php
require_once 'Zend/Validate/Abstract.php';
require_once 'Zend/Validate/Hostname.php';

require_once 'Zend/Validate/Exception.php';
 
class My_Validate_FieldCompare extends Zend_Validate_Abstract
{
    const MSG_NOT_EQ = 'fieldNotSame';
    const MSG_NOT_GT = 'fieldNotGreaterThan';
    const MSG_NOT_GE = 'fieldNotGreaterThanEqual';
    const MSG_NOT_LT = 'fieldNotLessThan';
    const MSG_NOT_LE = 'fieldNotLessThanEqual';

 
    const EQ = 'eq';
    const GT = 'gt';
    const GE = 'ge';
    const LT = 'lt';
    const LE = 'le';
 
    protected $_messageVariables = array(

        'key' => '_key',
        'key_value' => '_key_value'
    );
 
    protected $_messageTemplates = array(

        self::MSG_NOT_EQ => "'%value%' is not equal to '%key_value%'",
        self::MSG_NOT_GT => "'%value%' is not greater than '%key_value%'",
        self::MSG_NOT_GE => "'%value%' is not greater than or equal to '%key_value%'",
        self::MSG_NOT_LT => "'%value%' is not less than '%key_value%'",
        self::MSG_NOT_LE => "'%value%' is not less than or equal to '%key_value%'",
    );

 
    protected static $_tmp_operators = null;
    protected static $_tmp_values    = null;
    protected static $_key_errors    = null;
    protected static $_key_messages  = null;

 
 
    protected $_key      = null;
    protected $_operator = null;
    protected $_key_value = null;

 
    public function __construct($key, $operator = null)
    {
        $this->_key = $key;
        $this->_operator = $operator;
        self::$_key_errors[$key] = array();
        self::$_key_messages[$key] = array();
    }

 
    public function isValid($value)
    {
        if ($this->_operator && isset(self::$_tmp_values[$this->_key]))

        {
            $this->_key_value = self::$_tmp_values[$this->_key];
        }
        else if (!$this->_operator && isset(self::$_tmp_operators[$this->_key]))

        {
            $this->_key_value = $value;
            $this->_operator  = self::$_tmp_operators[$this->_key];
            $value            = self::$_tmp_values[$this->_key];
        }

        else if ($this->_operator && !isset(self::$_tmp_values[$this->_key]))

        {
            self::$_tmp_operators[$this->_key] = $this->_operator;
            self::$_tmp_values[$this->_key] = $value;
        }

        else if (!$this->_operator && isset(self::$_tmp_values[$this->_key]))

        {
            throw new Zend_Validate_Exception(
                'Field Compare Validator : operator does not specified(key=' .
                $this->_key . ')');
        }

        else if (!$this->_operator && !isset(self::$_tmp_operators[$this->_key]))

        {
            self::$_tmp_values[$this->_key] = $value;
        }
 
        $this->_setValue($value);
        if ($this->_key_value && $this->_operator)

        {
            switch($this->_operator)
            {
            case self::EQ :
                if ($value == $this->_key_value)

                {
                    return true;
                }
                $this->_error(self::MSG_NOT_EQ);
                return false;
            case self::GT :
                if ($value > $this->_key_value)

                {
                    return true;
                }
                $this->_error(self::MSG_NOT_GT);
                return false;
            case self::GE :
                if ($value >= $this->_key_value)

                {
                    return true;
                }
                $this->_error(self::MSG_NOT_GE);
                return false;
            case self::LT :
                if ($value < $this->_key_value)

                {
                    return true;
                }
                $this->_error(self::MSG_NOT_LT);
                return false;
            case self::LE :
                if ($value <= $this->_key_value)

                {
                    return true;
                }
                $this->_error(self::MSG_NOT_LE);
                return false;
            }

           throw new Zend_Validate_Exception(
               'Field Compare Validator : operator not found(key=' . $this->_key .
               ',op=' . $this->_operator . ')');
            return false;
        }

        return true;
    }
 
    /**
     * Sets the value to be validated and clears the messages and errors arrays
     *
     * @param  mixed $value
     * @return void
     */
    protected function _setValue($value)

    {
        parent::_setValue($value);
        self::$_key_errors[$this->_key] = array();
        self::$_key_messages[$this->_key] = array();
    }

 
    /**
     * @param  string $messageKey OPTIONAL
     * @param  string $value      OPTIONAL
     * @return void
     */
    protected function _error($messageKey = null, $value = null)

    {
        if ($messageKey === null) {
            $keys = array_keys($this->_messageTemplates);
            $messageKey = current($keys);
        }

        if ($value === null) {
            $value = $this->_value;
        }

        self::$_key_errors[$this->_key][] = $messageKey;
        self::$_key_messages[$this->_key][$messageKey] =
            $this->_createMessage($messageKey, $value);
    }

 
    /**
     * Returns array of validation failure messages
     *
     * @return array
     */
    public function getMessages()
    {
        if ($this->_operator)

        {
            return self::$_key_messages[$this->_key];
        }
        return array();
    }

 
    /**
     * Returns array of validation failure message codes
     *
     * @return array
     * @deprecated Since 1.5.0
     */
    public function getErrors()
    {
        if ($this->_operator)

        {
            return self::$_key_errors[$this->_key];
        }
        return array();
    }

 
}
2.Add Validator
Add the validator like the following content.

        $form = new Zend_Form();
        $form->addElementPrefixPath('My_Validate', 'My/Validate/',
                                    Zend_Form_Element::VALIDATE);
        //...
        $email = $form->createElement('text', 'email');
        $email->setLabel('E-Mail')
              ->setRequired(true)
              ->addFilter('stringTrim')
              ->addValidator('emailAddress', false)
              ->addValidator('fieldCompare', false, array('email'));
        $email2 = $form->createElement('text', 'email2');
        $email2->setLabel('E-Mail(Confirm)')
               ->setRequired(true)
               ->addFilter('stringTrim')
               ->addValidator('emailAddress', false)
               ->addValidator('fieldCompare', false, array('email', 'eq'));
        //...

This will execute the comparison $email == $email2.
The following is another example.

 
        $min = $form->createElement('text', 'min');
        $min->setLabel('Min Value')
              ->setRequired(true)
              ->addValidator('fieldCompare', false, array('min'));
        $value = $form->createElement('text', 'value');
        $value->setLabel('E-Mail(Confirm)')
               ->setRequired(true)
               ->addValidator('fieldCompare', false, array('min', 'ge'));
        //...

This will execute the comparison $value >= $min.

Comments:6

midix 09-07-18 (Sat) 20:06

Thanks, good one.

There is only one problem: if I use it for passwords, the %key_value% is being replaced by a visible password text, not *****.

I added one more operation EQPSW and message MSG_NOT_EQPSW which does not show %key_value%.

ninime 10-08-02 (Mon) 5:49

In complementary answer to midix, I set a certain echo mode, that replace the %key_value% instead of don’t show it.

Otherwise, continue your good works.

Maurice 12-08-10 (Fri) 21:02

There could be a problem when it comes to unit testing. So try to reset $_tmp_values while class construction.

Here is the cleaned constructor:
°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°

public function __construct($key, $operator = null)
{
$this->_key = $key;
$this->_operator = $operator;
self::$_key_errors[$key] = array();
self::$_key_messages[$key] = array();
self::$_tmp_values = null;
}

Now your testing problems should be resolved.

Maurice 12-08-10 (Fri) 22:44

// create class instance counter
protected static $_instances_created = 0;

// reset input list when two values were compared
public static function resetInputList()
{
if(self::$_instances_created == 2)
{
self::$_tmp_values = null;
self::$_instances_created = 0;
return true;
}

self::$_instances_created = self::$_instances_created + 1;
}

// construct and reset the compare list
public function __construct($key, $operator = null)
{
self::resetInputList();

$this->_key = $key;
$this->_operator = $operator;
self::$_key_errors[$key] = array();
self::$_key_messages[$key] = array();
self::$_tmp_operators = null;
}

Maurice 12-08-10 (Fri) 22:47

Sorry, my first post was wrong. Please refer to my second post where I only reset the list if a second instance of the class was created.

oplabo 12-09-09 (Sun) 23:26

Thank you very much!!

Comment Form
Remember personal info

Trackbacks:0

Trackback URL for this entry
http://www.oplabo.com/article/22/trackback
Listed below are links to weblogs that reference
Creating Fields Comparison Validator for Zend_Form from Open Programming Laboratory

Home > Zend_Validate > Creating Fields Comparison Validator for Zend_Form

Japanese
Search
Feeds

Return to page top