public function rules() {
//обычные валидаторы
$res = array(
array('attr_name', 'validator'),
);
//валидаторы, добавляемые по условию
if ($this->attr_name == 'some_value')
$res[] = array('attr_name', 'validator');
return $res;
}
Сначала опишу как решить проблему, а потом - почему такая проблема вообще возникает.
Дисклеймер: написанное справедливо для Yii PHP Framework 1.1.8, но поскольку для решения проблемы использовалась актуальная документация, то скорее всего проблема сохраняется и в текущей версии.
Решение
Изменяем модель следующим образом:
class ModelName extends CActiveRecord {
//переопределяем свойство, чтобы иметь доступ к нему
private $_validators;
/*
*
* содержание модели
*
*/
public function getValidatorList() {
if ($this->_validators === null)
$this->_validators = $this->createValidators();
return $this->_validators;
}
public function getValidators($attribute = null) {
if ($this->_validators === null)
$this->_validators = $this->createValidators();
$validators = array();
$scenario = $this->getScenario();
foreach ($this->_validators as $validator) {
if ($validator->applyTo($scenario)) {
if ($attribute === null || in_array($attribute, $validator->attributes, true))
$validators[] = $validator;
}
}
return $validators;
}
public function resetValidators() {
$this->_validators = null;
}
}
Функции getValidatorList() и getValidators() копируются из исходных кодов CModel без изменений. Далее весь фокус заключается в использовании написанной нами функции resetValidators(). Рассмотрим на примере стандартного контроллера:
public function actionUpdate($id) {
/*
* содержание экшна
*/
if (isset($_POST['ModelName'])) {
$model->attributes = $_POST['ModelName'];
//сброс валидаторов для обновления правил валидации
//в соответствии с изменёнными параметрами модели
$model->resetValidators();
if ($model->save()) {
$this->redirect(array('view', 'id' => $model->id));
}
}
//сброс валидаторов для корректного отображения (*) на форме
//(required-аттрибутов)
$model->resetValidators();
$this->render('update', array(
'model' => $model,
));
}
Почему так непросто
< подробнее будет позже, может быть : ) >
Если кратко, то массив с правилами валидации генерируется для модели один раз - при первом обращении к правилам валидации (кажется). Наша задача - обновлять эти правила. А дальше начинаются костыли с копированием методов, потому что в оригинальном CModel аттрибут $_validators является private. Был бы он protected - было бы интереснее. В данной ситуации также можно переопределить