Можно скомпоновать правила по сценариям, в вашем примере это выглядело бы так:
public function rules()
{
return array(
array('phone', 'length', 'max' => 12),
array('icq', 'length', 'max' => 9),
array('email', 'email'),
array('login', 'length', 'max' => 80),
array('email', 'length', 'max' => 200),
//registration
array('login, email, password, retypePassword', 'required', 'on'=>'registration'),
array('login, email', 'unique', 'on'=>'registration'),
array('login', 'match', 'pattern' => '~^[\da-zа-яёА-ЯЁ\.\-@_\+]+$~i', 'on'=>'registration'),
array('retypePassword', 'compare', 'compareAttribute' => 'password', 'on'=>'registration')
//updateByAdmin
array('login, email, password, retypePassword', 'required', 'on'=>'updateByAdmin'),
array('login, email', 'unique', 'on'=>'updateByAdmin'),
array('login', 'match', 'pattern' => '~^[\da-zа-яёА-ЯЁ\.\-@_\+]+$~i', 'on'=>'updateByAdmin'),
array('retypePassword', 'compare', 'compareAttribute' => 'password', 'on'=>'updateByAdmin')
//updateByModerator
array('email', 'required', 'on'=>'updateByAdmin'),
array('login', 'match', 'pattern' => '~^[\da-zа-яёА-ЯЁ\.\-@_\+]+$~i', 'on'=>'updateByAdmin'),
array('email', 'unique', 'on'=>'updateByAdmin'),
//changePassword
array('password, currentPassword, retypePassword', 'required', 'on'=>'changePassword'),
array('currentPassword', 'passwordValidator', 'on'=>'changePassword'),
array('retypePassword', 'compare', 'compareAttribute' => 'password', 'on'=>'changePassword')
//changeEmail
array('email, currentPassword', 'required', 'on'=>'changeEmail'),
array('email', 'unique', 'on'=>'changeEmail'),
array('currentPassword', 'passwordValidator', 'on'=>'changeEmail'),
);
}
В чем фишка всего этого? Кода, по сравнению с вашим примером, стало больше, но и его читаемость возросла.