I am trying to create an "edit user" page and want to ensure that the email address posted back is unique. Unique in this case means that it will exist in the database but only for the user whose details I am editing. No other user must have the same email address. I have this in validation rule in my UserForm (extends CFormModel):
array('email_address', 'unique',
'allowEmpty' => false,
'className' => 'User',
'caseSensitive' => false,
'message' => 'Another user has already registered with this email address.',
'criteria' => array(
'condition' => 'id != :id',
'params' => array(':id' => $this->id),
)
)
This does not work. It always takes $this->id as NULL. What am I doing wrong? Or is there another way to do this?
This won’t work because validator is instantiated BEFORE id is set. This is because rules() are needed to perform massive assignments (to determine safe attributes, etc) not only to validate already assigned values. You have to create your own validator which extends standard CUniqueValidator and sets proper criteria before caling parent validation method. This way you will have access to object being validated and its attributes (validation method is called when values are already set).
To be honest, I myself didn’t have a clear understanding how CUniqueValidator behaves differently for CActiveRecord and for CFormModel until I peeked into the source code.
To validate on your custom validator, you just use its alias path in the model rules. So if you have your custom validator class in /protected/components/validate/MyValidator.php, you would do this in your rules
public function rules() {
return array(
array('my_field', 'application.components.validate.MyValidator'),
);
}