Comments 19
Во первых, этот фрагмент лишний:
достаточно описать правила валидации.
Во вторых, сохраняя дочернюю модель в методе afterSave указанным способом мы можем получить ситуацию, когда первая модель сохранилась, а при сохранении второй возникли ошибки.
Подгрузку данных целесообразнее делать не в loadModel а переопределив метод CActiveRecord::populateRecord.
Я предпочитаю делать по другому. Если нет противопоказаний — не делить таблицы на аккаунт/профиль. Если деление все-же необходимо, то в завимсимости от конкретного случая либо работать с двумя моделями по отдельности:
либо создаю отдельную CFormModel, которая включает в себя все необходимые поля, описание различных сценариев валидации и логику сохранения данных.
Заранее извиняюсь, если где допустил ошибки в названиях
$model->name = $_POST['User']['name'];
$model->first_name = $_POST['User']['first_name'];
$model->description = $_POST['User']['description'];
достаточно описать правила валидации.
Во вторых, сохраняя дочернюю модель в методе afterSave указанным способом мы можем получить ситуацию, когда первая модель сохранилась, а при сохранении второй возникли ошибки.
Подгрузку данных целесообразнее делать не в loadModel а переопределив метод CActiveRecord::populateRecord.
Я предпочитаю делать по другому. Если нет противопоказаний — не делить таблицы на аккаунт/профиль. Если деление все-же необходимо, то в завимсимости от конкретного случая либо работать с двумя моделями по отдельности:
$user->attributes = $_POST['User'];
$profile->attributes = $_POST['Profile'];
$transaction = $db->beginTransaction();
if ($user->save() && $profile->save()) {
...
$transaction->commit();
} else {
$transaction->rollback();
}
либо создаю отдельную CFormModel, которая включает в себя все необходимые поля, описание различных сценариев валидации и логику сохранения данных.
Заранее извиняюсь, если где допустил ошибки в названиях
Если остановиться на вашем сценарии, я бы лучше переопределил метод save а не afterSave
А как быть, если понадобится вставить/обработать данные в БД консольной командой, а у нас save() и т.п. переопределен, и в нем $_POST?
Интуитивно, понимал, что делая вот так
я делаю, что то не правильно. Спасибо что, дали совет.
Хочу уточнить, правильно ли я понял идею относительно
такое возможно если мы в контроллере, например в actionCreate делаем так
а затем, при описании формы делаем следующее
То есть в рендер переедаю две модели, и при построении единой формы, использую поля из этих моделей.
$model->name = $_POST['User']['name'];
я делаю, что то не правильно. Спасибо что, дали совет.
Хочу уточнить, правильно ли я понял идею относительно
$user->attributes = $_POST['User'];
$profile->attributes = $_POST['Profile'];
такое возможно если мы в контроллере, например в actionCreate делаем так
public function actionCreate(){
$modelUser = new User();
$modelProfile = new Profile();
. . .
$this->render('form',array(
'modelUser'=>$modelUser,
'modelProfile'=>$modelProfile,
));
а затем, при описании формы делаем следующее
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'UserForm',
'enableAjaxValidation'=>false,
)); ?>
<?php echo $form->errorSummary($modelUser); ?>
<?php echo $form->errorSummary($modelProfile); ?>
<div class="row">
<?php echo $form->textField($modelUser,'login',array('size'=>45,'maxlength'=>45)); ?>
<?php echo $form->error($modelUser,'login'); ?>
</div>
<div class="row">
<?php echo $form->textField($modelProfile,'name'); ?>
<?php echo $form->error($modelProfile,'name'); ?>
</div>
. . .
То есть в рендер переедаю две модели, и при построении единой формы, использую поля из этих моделей.
Да, все верно. Для простоты можно передавать одну модельку, в контроллере написав
Естественно, должна быть определена связь 'profile'
$modelUser->profile = $modelProfile
или чуть более корректно $modelUser->setRelatedRecord('profile', $modelProfile, false);
Естественно, должна быть определена связь 'profile'
В метод
CActiveForm::errorSummary()
можно передать массив моделей.<?php echo $form->errorSummary(array($modelUser, $modelProfile)); ?>
$user->attributes = $_POST['User'];
Удобно конечно, но для пользователей (да и в админках) так лучше не делать. Вам могут прислать совершенно любые данные. Скажем сменить id записи дату или владельца. А если хочется так, то лучше делать какую-то подпись для списка параметров, которые действительно должны прийти от пользователя, хотя вроде еще можно помудрить с именованными наборами валидаций.
Правила валидации в Yii для этого и созданы
'name'=>'Имя',
'first_name'=>'Фамилия',
'description'=>'Описание'
Как же быть с локализацией?
С локализацией в этом примере полная лажа, согласен.
Но в этом примере, я ставил акцент на работе с CRUD двух связанных таблиц.
Если столкнусь с проблемами, при разработке локализации, то расскажу в следующем посте о их решении.
А если у Вас есть, какой то совет и ответ, милости прошу опубликовать его в комментарии ниже.
Но в этом примере, я ставил акцент на работе с CRUD двух связанных таблиц.
Если столкнусь с проблемами, при разработке локализации, то расскажу в следующем посте о их решении.
А если у Вас есть, какой то совет и ответ, милости прошу опубликовать его в комментарии ниже.
По-моему недостаток вашего подхода в том, что одна модель должна знать о наличии полей другой модели, а не только о связи с ней.
Для похожей задачи я использовал это расширение github.com/yiiext/activerecord-relation-behavior
Оно позволяет удобно задавать значения для связанных таблиц и прозрачно сохранять просто вызвав ->save().
В вашем случае если бы была связь Profile
'profile'=>array(self::HAS_ONE, 'profile', 'user_id'),
то код сохранения мог бы быть таким
$user = new User();
$user->attributes = $_POST['User'];
$user->profile->attributes = $_POST['Profile'];
$user->save();
Насчет удобства генерации форм в этом случае, не скажу. Главное, что это универсальное средство которое достаточно просто добавить в behaviors, чтоб оно заработало.
P.S. В этом расширении не реализована обработка удаления. Но оно легко допиливается. Если понадобится, могу поделиться собственной допиленной версией этого расширения с delete().
Для похожей задачи я использовал это расширение github.com/yiiext/activerecord-relation-behavior
Оно позволяет удобно задавать значения для связанных таблиц и прозрачно сохранять просто вызвав ->save().
В вашем случае если бы была связь Profile
'profile'=>array(self::HAS_ONE, 'profile', 'user_id'),
то код сохранения мог бы быть таким
$user = new User();
$user->attributes = $_POST['User'];
$user->profile->attributes = $_POST['Profile'];
$user->save();
Насчет удобства генерации форм в этом случае, не скажу. Главное, что это универсальное средство которое достаточно просто добавить в behaviors, чтоб оно заработало.
P.S. В этом расширении не реализована обработка удаления. Но оно легко допиливается. Если понадобится, могу поделиться собственной допиленной версией этого расширения с delete().
Возможно будет полезным CDbCommandBuilder::createMultipleInsertCommand()
Sign up to leave a comment.
Пошаговое руководство сохранения связанных данных Yii