CCompareValidator enhancement

It would be useful if CCompareValidator could also compare for non-equal values, e.g. to ensure old and new passwords are different.

Suggestion to support this.

Add an additional parameter



 /**


   * @var boolean whether the comparison is for non-equal values


   * Defaults to false.


   */


  public $notEqual=false;


This defaults to false, i.e. the default comparison is for equal values and so does not break existing applications.

The comparison test becomes:



    if(!$this->notEqual)


    {


      if(($this->strict && $value!==$compareValue) || (!$this->strict && $value!=$compareValue))


		  {


			  $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be repeated exactly.');


			  $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo));


		  }


    }


    else


    {


      if(($this->strict && $value===$compareValue) || (!$this->strict && $value==$compareValue))


      {


        $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must not be repeated exactly.');


        $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo));


      }


    }


I think it’d even better if one can specify the relation between values.

CCompareValidator::EQUAL (default)

CCompareValidator::NOT_EQUAL (Your suggestion)

CCompareValidator::GREATER

etc…

Developers then can add ‘type’=>CCompareValidator::NOT_EQUAL, so it has more flexibility.

(There should be others options if this is acceptable, such as GREATER_OR_EQUAL/NOT_LOWER, LOWER, LOWER_OR_EQUAL/NOT_GREATER.)

Go with that ;D: makes it totally general purpose for all comparions

Here's a suggestion for an implementation - a few class constants and a switch for the comparion:



class CCompareValidator extends CValidator


{


  const EQUAL=0;


  const NOT_EQUAL=1;


  const GREATER=2;


  const NOT_GREATER=3;


  const LESS=4;


  const NOT_LESS=5;





	/**


	 * @var string the name of the attribute to be compared with


	 */


	public $compareAttribute;


	/**


	 * @var string the constant value to be compared with


	 */


	public $compareValue;


  /**


   * @var integer The type of comparison to perform


   * Defaults to self::EQUAL.


   */


  public $type=self::EQUAL;


	/**


	 * @var boolean whether the comparison is strict (both value and type must be the same.)


	 * Defaults to false.


	 */


	public $strict=false;


	/**


	 * @var boolean whether the attribute value can be null or empty. Defaults to true,


	 * meaning that if the attribute is empty, it is considered valid.


	 */


	public $allowEmpty=true;





	/**


	 * Validates the attribute of the object.


	 * If there is any error, the error message is added to the object.


	 * @param CModel the object being validated


	 * @param string the attribute being validated


	 */


	protected function validateAttribute($object,$attribute)


	{


		$value=$object->$attribute;


		if($this->allowEmpty && ($value===null || $value===''))


			return;


		if($this->compareValue!==null)


			$compareTo=$compareValue=$this->compareValue;


		else


		{


			$compareAttribute=$this->compareAttribute===null ? $attribute.'_repeat' : $this->compareAttribute;


			$compareValue=$object->$compareAttribute;


			$compareTo=$object->getAttributeLabel($compareAttribute);


		}





    switch ($this->type)


    {


      case self::NOT_EQUAL:


        if(($this->strict && $value===$compareValue) || (!$this->strict && $value==$compareValue))


        {


          $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must not be equal to {compareAttribute}.');


          $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo));


        }


        break;


      case self::GREATER:


        if(($this->strict && gettype($value)!==gettype($compareValue)) || ($value<=$compareValue))


        {


          $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be greater than {compareAttribute}.');


          $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo));


        }


        break;


      case self::NOT_GREATER:


        if(($this->strict && gettype($value)!==gettype($compareValue)) || ($value>$compareValue))


        {


          $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must not be greater than {compareAttribute}.');


          $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo));


        }


        break;


      case self::LESS:


        if(($this->strict && gettype($value)!==gettype($compareValue)) || ($value>=$compareValue))


        {


          $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must not be less than {compareAttribute}.');


          $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo));


        }


        break;


      case self::NOT_LESS:


        if(($this->strict && gettype($value)!==gettype($compareValue)) || ($value<$compareValue))


        {


          $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must not be less than {compareAttribute}.');


          $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo));


        }


        break;


      default: //self::EQUAL


        if(($this->strict && $value!==$compareValue) || (!$this->strict && $value!=$compareValue))


        {


          $message=$this->message!==null?$this->message:Yii::t('yii','{attribute} must be equal to {compareAttribute}.');


          $this->addError($object,$attribute,$message,array('{compareAttribute}'=>$compareTo));


        }


        break;


    } // switch


  }


}


that would definitely be a cool enhancement

Thank you for your great inputs. Could you please create a ticket for this feature enhancement? Thanks.

Thanks Qiang! Ticket created: http://code.google.com/p/yii/issues/detail?id=456