Pull to refresh

Comments 12

Спасибо за статью.
от бы еще на клиент эти динамические правила передать, чтобы для подсветки required поля не делать лишний запрос.
А почему у вас в коде есть параметр validateOnSubmit но нету afterValidate? Или это описка?
Не понял зачем вы поместили код изменения сценария в метод performAjaxValidation. В этом случае сценарий не будет использован если форму отправили обычным способом. Я бы сделал так
public function actionSaveCall(){ $model=new Calls('callSubmit'); if( isset($_POST['Calls']) && isset($_POST['Calls']['call_status']) ) { switch($_POST['Calls']['call_status']) { case Calls::CALL_FAIL: $model->setScenario('validCallSubmit'); break; case Calls::SUCCESS_CALL: $model->setScenario('successCallSubmit'); break; case Calls::WRONG_NUMBER: $model->setScenario('invalidNumberSubmit'); break; } $this->performCallAjaxValidation($model); ... } }
мда красиво оно отформатировало. Для тех кому лень вставлять «это» в редактор я вынес установку сценария в метод actionSaveCall перед вызовом метода performCallAjaxValidation
Если сценариев будет много, то довольно накладно будет писать много конструкций case.
Тут недостаток в другом — что я не сделал это в ООП-манере и не вынес этот массив и само изменение сценария из метода performAjaxValidation, но я предупредил о том, что не заморачиваюсь об этом. В идеале этот массив лучше было ы хранить в определенном конфиге и вытягивать его в свойство модели в методе __construct().
Если сценариев будет много возникнет другая проблема. Прописывать правила валидации для большого количества сценариев очень неудобно в том виде как это реализовано в Yii
Ну для того чтобы запилить в метод rules много сценариев валидации, можно вынести их из модели в какой-то легко читаемый конфиг, например в формате YAML (.yml), и потом из этого конфига читать эти правила при инициализации модели. Алгоритм прост — читается конфиг, превращается в массив, делается implode(",", $configArray), массив всех правил, возвращаемых методом rules берется в свойство, и затем все правила, которые нужно добавить, добавляются туда с помощью array_push(). Ну а сам метод rules возвращает это свойство.
Но вы правы, эту работу нужно проделать самому. Правда и то, что в Yii разделение логики более слабое, нежели в том же Symfony2.
Мне не кажется способ вынесения правил валидации в отдельный файл хорошим решением. Тем более что в остальных моделях правила находятся в их классе. А вообще нет ничего удивительного что в yii не так удобно работать с большим количеством сценариев. Этот случай на столько редкий что жертвовать красотой настройки ради этих случаев глупо. Тем более что даже в тех случаях проблема скорее в не правильном написании кода чем в необходимости. Я уверен что сценариев не должно быть много.
>>Мне не кажется способ вынесения правил валидации в отдельный файл хорошим решением.
На самом деле это хорошее и правильное решение, так как способствует еще большему разделению ответственности и логики на понятные составляющие. Но вы правы в том, что все должно быть по одному стандарту — если выносить правила, то тогда уже во всех моделях.
В симфони все это выносится в отдельные сущности, правда вам для этого не нужно писать код для обработки этих сущностей, так как это разделение заложено в фреймворке. И должен сказать, по поводу «жертвовать красотой» вы не правы, так как такое разделение в симфони выглядит значительно красивее чем метод rules в моделях в Yii — это и читабельнее, и красивее, и гибче.
Да, кстати, спасибо большое на ценное указание по поводу afterValidate — после валидации желательно убрать «зеленую подсветку» у тех полей, у которых она осталась с прошлых валидаций. Добавлю в пост скоро.
имхо, вы выбрали неверный путь для валидации полей зависящих от значения других полей.
недостатки:
1. теряется наглядность при изучении модели
2. нужно создавать дополнительный код в котроллере для обеспечения смены сценария
3. что если кто то переименует сценарии?

На мой взгляд задача довольно очевидная — «Обеспечить валидацию полей зависимых от значения других полей».
Т. е. нужно создать новый клас валидации (конечно же унаследовав существующий валидатор), и добавить ему функционал, который позволит обрабатывать ситуации в зависимости от других параметров.

вот пример такого валидатора:
class ExRequiredValidator extends CRequiredValidator{
	
	public $strict = true;
	/**
	 * makes validation depend on some another attribute value
	 * useful when some fileds of form are hidden based on appropriate attribute
	 * @var string
	 */
	public $boundAttribute = null;
	
	/**
	 * @var string
	 */
	public $boundAttributeValue = null;


ну и правила в модели:

public function rules(){
	return array(
		array('call_status','required','message'=>'Required field'),
		array('talk_status','ExRequiredValidator','boundAttribute'=>'call_status','boundAttributeValue'=>'success','message'=>'Required field'),
		);
}


Похоже, что ваше решение более правильное, чем мое. Я еще не совсем разобрался в вашем примере — нужно применить его на практике, чтобы было нагляднее.
В целом же спасибо за ценный совет.
видимо правила в модели не влезли на страницу:
public function rules(){
    return array(
        array('call_status','required','message'=>'Required field'),
        array('talk_status','ExRequiredValidator','boundAttribute'=>'call_status','
boundAttributeValue'=>'success','message'=>'Required field'),
        );
}
Sign up to leave a comment.

Articles