Сохранение связанных моделей

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Сохранение связанных моделей

Сообщение codrilla »

Никак не могу сделать сохранение связанных моделей. Ситуация такая:
В модели Car есть связь

Код: Выделить всё

public function getPhotos()
    {
        return $this->hasMany(Photo::className(), ['car_id' => 'id']);
    }
 
Экшен создания Саr выглядит следующим образом

Код: Выделить всё

public function actionCreate()
    {
        if (Yii::$app->user->can('createCar')) {
            $model = new Car;
            //$modelPhoto = new Photo;

            if ($model->load(Yii::$app->request->post())) {
                $modelPhoto = new Photo;
                $images = UploadedFile::getInstances($modelPhoto, 'image');
                foreach ($images as $image) {

                    $modelPhoto = new Photo;

                    $modelPhoto->image = $image;

                    $model->link('photos', $modelPhoto);  //вот эта строка не сработает, потому что ещё ни одна модель не сохранена
                                                                            //$model->photos[] = $modelPhoto так же не сработает (идея взята отсюда http://yiiframework.ru/doc/cookbook/ru/model.save.related.data). Выводится ошибка
                }
                if ($model->save()) {
                    return $this->redirect(['view', 'id' => $model->id]);
                }
            } else {
                $modelPhoto = new Photo();
                return $this->render(
                    'create',
                    [
                        'model' => $model,
                        'modelPhoto' => $modelPhoto
                    ]
                );
            }
        } else {
            throw new HttpException('403', Yii::t('app', 'У вас нет прав для публикации объявлений'));
        }
    }
 
Ну и afterSave планирую сделать таким

Код: Выделить всё

public function afterSave($insert)
    {
        parent::afterSave($insert);
        foreach ($this->photos as $photo) {
            $photo->car_id = $this->id;
            $photo->save();
        }
    }
 
Подскажите, пожалуйста, как сделать это правильно. Заранее благодарен.
Аватара пользователя
mihail_dev
Сообщения: 243
Зарегистрирован: 2013.07.17, 00:51
Откуда: Молдова
Контактная информация:

Re: Сохранение связанных моделей

Сообщение mihail_dev »

если везде в остальном всё правильно то экшин должен по идее выглядеть примерно так

Код: Выделить всё

public function actionCreate()
    {
        if (Yii::$app->user->can('createCar')) {
            $model = new Car;
            $modelPhoto = new Photo;

            if ($model->load(Yii::$app->request->post())) {
                if ($model->save()) {
                    $images = UploadedFile::getInstances($modelPhoto, 'image');
                    foreach ($images as $image) {

                        $image->saveAs('some file name here');

                        $photo = new Photo;

                        $photo->image = $image;

                        $model->link('photos', $photo);
                    }

                    $this->redirect(['view', 'id' => $model->id]);
                }
            }

            return $this->render(
                        'create',
                            [
                                'model' => $model,
                                'modelPhoto' => $modelPhoto
                            ]
            );

        } else {
            throw new HttpException('403', Yii::t('app', 'У вас нет прав для публикации объявлений'));
        }
    }
Изображение
codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Re: Сохранение связанных моделей

Сообщение codrilla »

Да. Этот вариант действительно сработает. Просто ситуация такая, что связанные модели мне бы хотелось сохранять в afterSave основной модели, чтобы не дублировать потом тот же самый код в actionUpdate например, да и логически смотрится более правильно.
codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Re: Сохранение связанных моделей

Сообщение codrilla »

И как я понял link использовать не получится, т.к. оригинальная модель Car ещё не сохранена и как следствие не имеет primary key. Не понятно, как избавиться от ошибки Indirect modification of overloaded property, когда делаю $model->photos[] = $modelPhoto
codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Re: Сохранение связанных моделей

Сообщение codrilla »

Видимо придётся отказаться от afterSave в Car и делать link в контроллере. Неужели так и не появилось в yii2 сохранение связанных моделей?
Аватара пользователя
mihail_dev
Сообщения: 243
Зарегистрирован: 2013.07.17, 00:51
Откуда: Молдова
Контактная информация:

Re: Сохранение связанных моделей

Сообщение mihail_dev »

можно не отказываться просто в модель кар добавить публичную переменную с другим названием отличным от photos ну к примеру photosForSave
ошибка выдаётся так как у вас нет сеттера скорее всего в моделе кар а геттер у вас связь (public function getPhotos())
Изображение
codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Re: Сохранение связанных моделей

Сообщение codrilla »

Над этим вариантом тоже думал. А можно ли как-то задать сеттер для связи?
Аватара пользователя
mihail_dev
Сообщения: 243
Зарегистрирован: 2013.07.17, 00:51
Откуда: Молдова
Контактная информация:

Re: Сохранение связанных моделей

Сообщение mihail_dev »

public function setPhotos($value){
$this->some = $value;
}
Изображение
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Сохранение связанных моделей

Сообщение zelenin »

codrilla писал(а):Да. Этот вариант действительно сработает. Просто ситуация такая, что связанные модели мне бы хотелось сохранять в afterSave основной модели, чтобы не дублировать потом тот же самый код в actionUpdate например, да и логически смотрится более правильно.
а разве link не сохраняет в БД?
Аватара пользователя
mihail_dev
Сообщения: 243
Зарегистрирован: 2013.07.17, 00:51
Откуда: Молдова
Контактная информация:

Re: Сохранение связанных моделей

Сообщение mihail_dev »

zelenin писал(а):
codrilla писал(а):Да. Этот вариант действительно сработает. Просто ситуация такая, что связанные модели мне бы хотелось сохранять в afterSave основной модели, чтобы не дублировать потом тот же самый код в actionUpdate например, да и логически смотрится более правильно.
а разве link не сохраняет в БД?
link сохраняет модель которую связывает но не основную
Изображение
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Сохранение связанных моделей

Сообщение zelenin »

mihail_dev писал(а):
zelenin писал(а):
codrilla писал(а):Да. Этот вариант действительно сработает. Просто ситуация такая, что связанные модели мне бы хотелось сохранять в afterSave основной модели, чтобы не дублировать потом тот же самый код в actionUpdate например, да и логически смотрится более правильно.
а разве link не сохраняет в БД?
link сохраняет модель которую связывает но не основную
ну так вы и сохраняете не основные

Код: Выделить всё

foreach ($this->photos as $photo) {
            $photo->car_id = $this->id;
            $photo->save();
        }
 
codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Re: Сохранение связанных моделей

Сообщение codrilla »

mihail_dev писал(а):public function setPhotos($value){
$this->some = $value;
}
И что такое в моём контексте $this->some?
codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Re: Сохранение связанных моделей

Сообщение codrilla »

zelenin писал(а): ну так вы и сохраняете не основные
Такое сохранение в контроллере предложили позже. Я же изначально хотел сделать сохранение связанных моделей в afterSave
codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Re: Сохранение связанных моделей

Сообщение codrilla »

Если кому-то интересно, в итоге сделал так:

Код: Выделить всё

/**
     * Creates a new Car model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     * @throws \yii\web\HttpException
     * @return mixed
     */
    public function actionCreate()
    {
        if (Yii::$app->user->can('createCar')) {
            $model = new Car;
            $modelPhoto = new Photo;

            if ($model->load(Yii::$app->request->post()) && $model->save()) {
                $images = UploadedFile::getInstances($modelPhoto, 'image');
                foreach ($images as $image) {

                    $modelPhoto = new Photo;

                    $modelPhoto->image = $image;

                    $model->link('photos', $modelPhoto);
                }

                return $this->redirect(['view', 'id' => $model->id]);

            } else {
                $modelPhoto = new Photo();
                return $this->render(
                    'create',
                    [
                        'model' => $model,
                        'modelPhoto' => $modelPhoto
                    ]
                );
            }
        } else {
            throw new HttpException('403', Yii::t('app', 'У вас нет прав для публикации объявлений'));
        }
    }

    /**
     * Updates an existing Car model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id
     * @throws \yii\web\HttpException
     * @return mixed
     */
    public function actionUpdate($id)
    {
        $model = $this->findModel($id);
        if (Yii::$app->user->can('updateCar', ['car' => $model])) {

            $modelPhoto = new Photo;
            $modelsPhoto = $model->photos;

            if ($model->load(Yii::$app->request->post()) && $model->save()) {
                $images = UploadedFile::getInstances($modelPhoto, 'image');
                foreach ($images as $image) {

                    $modelPhoto = new Photo;

                    $modelPhoto->image = $image;

                    $model->link('photos', $modelPhoto);
                }

                return $this->redirect(['view', 'id' => $model->id]);
            } else {
                return $this->render(
                    'update',
                    [
                        'model' => $model,
                        'modelsPhoto' => $modelsPhoto,
                        'modelPhoto' => $modelPhoto
                    ]
                );
            }
        } else {
            throw new HttpException('403', Yii::t('app', 'У вас нет прав для редактирования данного объявления'));
        }
    }
 
codrilla
Сообщения: 173
Зарегистрирован: 2013.03.06, 12:24
Откуда: Молдова, Тирасполь

Re: Сохранение связанных моделей

Сообщение codrilla »

С сеттером для связи всё равно хотелось бы разобраться
Аватара пользователя
vova07
Сообщения: 1004
Зарегистрирован: 2012.11.29, 14:52
Откуда: Chisinau, Moldova

Re: Сохранение связанных моделей

Сообщение vova07 »

Код: Выделить всё

public function actionCreate()
{
    if (Yii::$app->user->can('createCar')) {
        $model = new Car;
        $modelPhoto = new Photo;

        if ($model->load(Yii::$app->request->post())) {
            $images = UploadedFile::getInstances($modelPhoto, 'image');
            $model->populateRelation('photos', $images);

            if ($model->save(false)) {
                return $this->redirect(['view', 'id' => $model->id]);
            }

        } else {
            $modelPhoto = new Photo();
            return $this->render(
                'create',
                [
                    'model' => $model,
                    'modelPhoto' => $modelPhoto
                ]
            );
        }
    } else {
        throw new HttpException('403', Yii::t('app', 'У вас нет прав для публикации объявлений'));
    }
}
Аватара пользователя
mihail_dev
Сообщения: 243
Зарегистрирован: 2013.07.17, 00:51
Откуда: Молдова
Контактная информация:

Re: Сохранение связанных моделей

Сообщение mihail_dev »

vova07 писал(а):

Код: Выделить всё

public function actionCreate()
{
    if (Yii::$app->user->can('createCar')) {
        $model = new Car;
        $modelPhoto = new Photo;

        if ($model->load(Yii::$app->request->post())) {
            $images = UploadedFile::getInstances($modelPhoto, 'image');
            $model->populateRelation('photos', $images);

            if ($model->save(false)) {
                return $this->redirect(['view', 'id' => $model->id]);
            }

        } else {
            $modelPhoto = new Photo();
            return $this->render(
                'create',
                [
                    'model' => $model,
                    'modelPhoto' => $modelPhoto
                ]
            );
        }
    } else {
        throw new HttpException('403', Yii::t('app', 'У вас нет прав для публикации объявлений'));
    }
} 
а в самой моделе как обработать оно же автоматом не привяжет?
Изображение
Аватара пользователя
vova07
Сообщения: 1004
Зарегистрирован: 2012.11.29, 14:52
Откуда: Chisinau, Moldova

Re: Сохранение связанных моделей

Сообщение vova07 »

Задача состояла в красивой передачи данных в модель. Код это решает.
А сохранение я обычно делаю в afterSave с включенными транзакциями для того чтобы сбросить все обратно в случае неудачи.

Код: Выделить всё

public function afterSave($insert)
{
    parent::afterSave($insert);

    if ($this->photos !== null) {
        //  Сохраняем наши связи
    }
} 
Аватара пользователя
mihail_dev
Сообщения: 243
Зарегистрирован: 2013.07.17, 00:51
Откуда: Молдова
Контактная информация:

Re: Сохранение связанных моделей

Сообщение mihail_dev »

vova07 писал(а):Задача состояла в красивой передачи данных в модель. Код это решает.
А сохранение я обычно делаю в afterSave с включенными транзакциями для того чтобы сбросить все обратно в случае неудачи.

Код: Выделить всё

public function afterSave($insert)
{
    parent::afterSave($insert);

    if ($this->photos !== null) {
        //  Сохраняем наши связи
    }
}
да но если там уже есть фоты какие то над делать проверку связанно или нет или как?
Изображение
Аватара пользователя
vova07
Сообщения: 1004
Зарегистрирован: 2012.11.29, 14:52
Откуда: Chisinau, Moldova

Re: Сохранение связанных моделей

Сообщение vova07 »

При первой вставки связь будет пуста, так что тут все понятно, если при обновлении вы не выводите для редактирования все фотки то проверка нужна будет, если выводите те что уже сохранены и загружаете новые, то то что я написал подойдет для такого случая.
Если не нравится обновлять связи при каждом сохранении, то можете проверять если их сохранение необходимо и только тогда делать это.
Ответить