Yii: всегда учитывайте неудачный save модели
2 мая 2011
Те, кто раньше не работал с Yii, на первых порах часто совершают очень нехорошую ошибку:
$model = new Post(); if(!empty($_POST['Post'])) { $model->attributes = $_POST['Post']; $model->save(); $this->redirect(array()); } $this->render('form', array( 'model' => $model, ));
Вот такой, казалось бы, простой код убить может немало нервов. Дело в том, что save
запросто может не сработать, если не выполнится правило валидации. А т.к. мы этого не проверили, произойдёт редирект без каких-либо признаков ошибки.
Комментарии RSS по email OK
У меня проще, много раз об этом писал, но всем показалось неудобным :) :
За метод saved отвечает поведение - EFormModelBehavior
Тут вообще вариаций много. Я предпочитаю вызывать validate сперва, да и в общем-то Gii так генерит. Иногда до валидации по событию что-то сделать надо или после валидации, а потом уже и сам save делаю. Местами вообще всё в транзакции занесено.
Но основная ошибка типична и многие натыкаются.
Вообще, по хорошему, при не прохождении валидации должно кидаться исключение, жалко что изначально в Yii так не реализовано.
Serge, непрохождение валидации — это вполне штатная ситуация. В большинстве случаев необходимо выводить ошибки в форму, а не кидать исключение, поэтому
try-catch
вместоif
сильно раздули бы код и сделали бы его не очень красивым.2Sam: Я говорил о том моменте когда пользователь пытается сохранить модель не прошедшую валидацию в БД, именно тогда нужно кидать исключение, в других случаях я соглашусь что кидание исключения будет излишним. :)
2Serge, В корне не согласен. Никто не мешает подключить поведение типа:
Тем самым мы убираем еще один if и сворачиваем все в конструкцию:
Так что если не устраивает вариант по умолчанию, выше я описал альтернативу для избежания подобных ошибок.
2Ekstazi: Внесу немного ясности про моё высказывание про исключение. Оно должно кидаться только тогда, когда вызван метод save() и модель не валидна! Это позволит избежать ошибки описанной в данной статье. И действительно жаль что такое не реализованно по умолчанию в модели Yii
А вы разве не знаете что save еще и валидацию делает ?
Поддержу Serge. Мне должно быть абсолютно пофиг, делает save валидацию, или не делает - это же реализация метода, инкапсулированная логика. То, что save возвращает false - не говорит о характере ошибки, и в этом есть запах дурного кода. Код бизнес логики должен быть скрыт за интерфейсом. Обработка ошибок через исключения - часть этого интерфейса. Безусловно, паттерн Валидатор чрезвычайно удобен. Когда мы выполняет явную проверку типа isValid, то естественно ожидается boolean. Но когда я сохраняю объект, то я ничего не ожидаю. При любой ошибке сохранения желателен Exception, так как уровней вложенности сохранения может быть очень много при развитом домене с большим числом relations. В случае ifов будет настоящий говнокод, везде придется учитывать, что же вернул save. А мог бы быть один блок try catch на всю транзакцию. Exception объясняет, что может произойти при исполнении save, это хорошая документация.
Если выполняется проверка - ожидается bool как результат. Если произошла ошибка выполнения - exception. Работа save - не проверка, следовательно более правильным считаю exception
Я работаю над проектом legacy, все ошибки на if . Без слез не взглянешь на это.
Помогите в топике пожалуйста http://www.yiiframework.com/forum/index.php?/topic/19386-%d0%bf%d0%be%d0%bb%d1%83%d1%87%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d1%81%d0%b2%d1%8f%d0%b7%d0%b0%d0%bd%d0%bd%d0%be%d0%b9-%d0%bc%d0%be%d0%b4%d0%b5%d0%bb%d0%b8-many-many-%d0%b2-cactivedataprovider/
А как такое может быть, что была ошибка валидации, а $model->errors пустой? Это я про Yii 2 спрашиваю .
Виталий, лучше с вопросами на форум yiiframework.ru.
You have to use try-catch anyway, because PDO may throw exception.
Правильно ли я понимаю, проверять save() необходимо также и по причине "а вставились ли вообще данные в таблицу"?
Ну да.