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

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
surrealistic_pillow
Сообщения: 39
Зарегистрирован: 2016.11.22, 18:14

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

Сообщение surrealistic_pillow »

Имеется три модели
Request
ModuleEntry - промежуточная таблица для связи (request_id, module_id, edu_form_id). edu_form_id здесь - форма обучения: 0-заочно и 1- очная форма
Module

Суть в том что пользователь подает заявку на обучение, выбирает при этом модули. Т.е. одной записи из таблицы requests соответствует несколько записей из таблицы module_entries (hasMany).

В модели Request:

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

    public function getModuleEntry()
    {
        return $this->hasMany(ModuleEntry::className(), ['request_id' => 'id']);
    }
В модели ModuleEntry:

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

    public function getModule()
    {
        return $this->hasOne(Module::className(), ['id' => 'module_id']);
    }
    public function getRequest()
    {
        return $this->hasOne(Request::className(), ['id' => 'request_id']);
    }
RequestController:

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

public function actionUpdate($id)
    {
        $model = $this->findModel($id);
        $checked_modules = $this->initCheckedModules($model);
        
        if ($model->load(Yii::$app->request->post()) && $model->save()) {
                      
            $this->processCheckedModules($checked_modules, $model);   
            
            return $this->redirect(['view', 'id' => $model->id]);
        } else {
            return $this->render('update', [
                'model' => $model,
                'checked_modules' => $checked_modules,                
            ]);
        }
    }
private function initCheckedModules(Request $model){
        
        $checked_modules = $model->getModuleEntry()
                ->indexBy('module_id')->all();
        
        $modules = Module::find()->where(['category'=>$model->program->id])->indexBy('id')->all();
        
        foreach (array_diff_key($modules, $checked_modules) as $module) {
            $checked_modules[$module->id] = new ModuleEntry(['module_id' => $module->id]);
        }     
     
        return $checked_modules;
}

private function processCheckedModules($checked_modules, Request $model){
        foreach ($checked_modules as $checked_module) {
            $checked_module->request_id = $model->id;
            if ($checked_module->validate()) {
                if ($checked_module->edu_form_id!==null) { //значение edu_form_id может принять только 0-заочно и 1- очная форма
                    $checked_module->save(false);
                } else {
                    $checked_module->delete();
                }
            }
        }
    }
/views/request/_form.php
Вывожу чекбокслист выбора формы обучения для каждого из модулей в форме редактирования заявки:

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

	<?php foreach($checked_modules as $checked_module){?>
                <?=$form->field($checked_module, '['.$checked_module->module->id.']edu_form_id')->checkboxList([0=>'Дистанционно', 1=>'Очно'])->label($checked_module->module->fullname);?>
	<? }?>
В результате в форме все выводится надлежащим образом, т.е. отмечена выбранная форма обучения для каждого из выбранных модулей, для тех модулей, которые человек не выбрал при подаче заявки, чекбоксы пустые (выбран может быть только один чекбокс для каждого модуля, типа как radioList, только с возможностью снять все чекбоксы для модуля):
Изображение

Проблема в том, что некорректно сохраняются данные из этой формы.
например, в update при сохранении (даже если я не меняю отмеченные чекбоксы), из таблицы module_entries удаляются все значения соответствующие заявке(request_id) и выбранным модулям(module_id) с edu_form_id = 0, остаются только записи с edu_form_id = 1

При попытках дальнейшего редактирования (снимаем или ставим чекбоксы напротив нужных модулей) никаких изменений не происходит, записи в module_entries остаются прежними.

Что я делаю не так? Не могу понять, уже всю голову сломал, помогите пожалуйтса
Ответить