Search code examples
zend-frameworkzend-formcustomvalidator

Custom validator not work in Zend


I have a custom validator NoOtherUsed: to check if the email is already used by another user

class Toxter_Validate_NoOtherUsed extends Zend_Validate_Abstract
{
    protected $_parameters;
    protected $_messageTemplates = array();
    const ALREADY_USED = 'alreadyused';

    public function __construct($parameters) {
      $this->_parameters = $parameters;      
      $this->_messageTemplates[self::ALREADY_USED] =  $this->_parameters['message'];
   }

    public function isValid($value)
    {
        $db = Zend_Registry::get('db');
        $sql = 'SELECT * FROM '.$this->_parameters['table'].' WHERE '.
                $this->_parameters['query_field'].' != \''. $this->_parameters['query_value'].
                '\' AND '.$this->_parameters['field'].' = \''.$value.'\'';

        $stmt = $db->query($sql);
        $result = $stmt->fetchall();
        $rowCount = sizeof($result);

        if($rowCount > 0){
            $this->_error(self::ALREADY_USED);
            return false;
        }

        return true;
    }
}

I used this validator in the form:

$this->createElement('text', 'email')
                        ->setLabel('Email')            
                        ->addValidator(new Zend_Validate_EmailAddress(), true)
                        ->addValidator(new Toxter_Validate_NoOtherUsed(array(
                            'table' => 'user',
                            'query_field' => 'id',
                            'query_value' => $currentUser->getRecord()->getId(),
                            'field' => 'email',
                            'message' => 'This email is used by another user'
                            )), true)
                        ->addValidator(new Toxter_Validate_NoOtherUsed(array(
                            'table' => 'email',
                            'query_field' => 'user_id',
                            'query_value' => $currentUser->getRecord()->getId(),
                            'field' => 'address',
                            'message' => 'This email is used by another user'
                        )), true)
                        ->addFilter(new Zend_Filter_StringTrim())

I used the custom validator 2 times. I intend to check if there's another user used this email and check if this email used on email table (contain all email belong to one user).

Problem is the later validator will run and check correctly but the other will not run. So i just can check if there's a user used this email, or check if the email already on email list of someone else. Can not check both of them.

Could anybody give me a reason ?

Thanks!


Solution

  • The problem is that the validators attached to an element are keyed by classname, so the second one is overwriting the first.

    What you need to to do is create a validator chain containing your two custom validator instances and attach the chain to your element. See the workaround at the end of this entry in the ZF issue tracker:

    [#ZF-6904] Two Validators of the same class can not be used two times for a field in form to validate two values in db - Zend Framework Issue Tracker

    Thanks to JeremyKendall for originally pointing out the issue report and the workaround.