Hello everyone) I have a table of teachers, a table of subjects and a teachers_subjects table (intermediate table). I need to use a many to many connection. But there is a problem. To create a CRUD, I used Gii. But he himself apparently does not know how to create forms for working with related tables. So I corrected the code. In the form of adding teachers, I added the Subjects field (Subjects are displayed from the Subjects table), all the subjects are displayed in the form of checkboxes. Actually this is the problem, how to make the selected checkboxes recorded in an intermediate table? At the moment, after saving, only the data in the Teachers table is saved, but how to make the record in the intermediate table? Help me please :(

Model Teachers

<?php namespace app\models; use yii\db\ActiveRecord; class Teachers extends ActiveRecord { public static function tableName() { return 'teachers'; } public function getSubjectsId() { return $this->hasMany(Subjects::className(), ['id' => 'subjects_id']) ->viaTable('teachers_subjects', ['teachers_id' => 'id']); } } 

Teachers Controller

 <?php namespace app\controllers; use Yii; use app\models\Teachers; use app\models\TeachersSearch; use app\models\Departments; use app\models\Posts; use app\models\Subjects; use yii\web\Controller; use yii\web\NotFoundHttpException; use yii\filters\VerbFilter; use yii\helpers\ArrayHelper; /** * TeachersController implements the CRUD actions for Teachers model. */ class TeachersController extends Controller { /** * @inheritdoc */ public function behaviors() { return [ 'verbs' => [ 'class' => VerbFilter::className(), 'actions' => [ 'delete' => ['POST'], ], ], ]; } /** * Lists all Teachers models. * @return mixed */ public function actionIndex() { $searchModel = new TeachersSearch(); $dataProvider = $searchModel->search(Yii::$app->request->queryParams); return $this->render('index', [ 'searchModel' => $searchModel, 'dataProvider' => $dataProvider, ]); } /** * Displays a single Teachers model. * @param integer $id * @return mixed */ public function actionView($id) { $teacher = Teachers::findOne($id); $departmentName = $teacher->departmentIdName; //die($departmentName); //die($departmentName); $postName = $teacher->postIdName; //die($postName); return $this->render('view', [ 'model' => $this->findModel($id), 'departmentName' => $departmentName, 'postName' => $postName, ]); } /** * Creates a new Teachers model. * If creation is successful, the browser will be redirected to the 'view' page. * @return mixed */ public function actionCreate() { $model = new Teachers(); $subjects = Subjects::find()->all(); $department = new Departments(); $facultiesWithDepartment = $department->find()->with('facultyId')->asArray()->all(); $posts = Posts::find()->all(); if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); } else { return $this->render('create', [ 'model' => $model, 'facultiesWithDepartment' => $facultiesWithDepartment, 'posts' => $posts, 'subjects' => $subjects ]); } } /** * Updates an existing Teachers model. * If update is successful, the browser will be redirected to the 'view' page. * @param integer $id * @return mixed */ public function actionUpdate($id) { $model = $this->findModel($id); $department = new Departments(); $facultiesWithDepartment = $department->find()->with('facultyId')->asArray()->all(); $posts = Posts::find()->all(); if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); } else { return $this->render('update', [ 'model' => $model, 'facultiesWithDepartment' => $facultiesWithDepartment, 'posts' => $posts, ]); } } /** * Deletes an existing Teachers model. * If deletion is successful, the browser will be redirected to the 'index' page. * @param integer $id * @return mixed */ public function actionDelete($id) { $this->findModel($id)->delete(); return $this->redirect(['index']); } /** * Finds the Teachers model based on its primary key value. * If the model is not found, a 404 HTTP exception will be thrown. * @param integer $id * @return Teachers the loaded model * @throws NotFoundHttpException if the model cannot be found */ protected function findModel($id) { if (($model = Teachers::findOne($id)) !== null) { return $model; } else { throw new NotFoundHttpException('The requested page does not exist.'); } } } 

View Create.php

 <?php use yii\helpers\Html; /* @var $this yii\web\View */ /* @var $model app\models\Teachers */ $this->title = 'Create Teachers'; $this->params['breadcrumbs'][] = ['label' => 'Teachers', 'url' => ['index']]; $this->params['breadcrumbs'][] = $this->title; ?> <div class="teachers-create"> <h1><?= Html::encode($this->title) ?></h1> <?= $this->render('_form', [ 'model' => $model, 'facultiesWithDepartment' => $facultiesWithDepartment, 'posts' => $posts, 'subjects' => $subjects, ]) ?> </div> 

And _form.php

 <?php use yii\helpers\Html; use yii\widgets\ActiveForm; use yii\helpers\ArrayHelper; /* @var $this yii\web\View */ /* @var $model app\models\Teachers */ /* @var $form yii\widgets\ActiveForm */ ?> <div class="teachers-form"> <?php $form = ActiveForm::begin(); ?> <?= $form->field($model, 'surname')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'patronymic')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'post')->dropDownList(ArrayHelper::map($posts, 'id', 'name'), ['options' => [$model->post => ['Selected'=>'selected']]]) ?> <?= $form->field($model, 'degree')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'rank')->textInput(['maxlength' => true]) ?> <?= $form->field($model, 'load')->textInput() ?> <?= $form->field($model, 'departments')->dropDownList(ArrayHelper::map($facultiesWithDepartment, 'id', 'name', function($facultiesWithDepartment, $defaultValue) { return 'Факультет - ' . $facultiesWithDepartment['facultyId']['name']; }), ['options' => [$model->departments => ['Selected'=>'selected']]]) ?> <?= $form->field($model, 'subjectsId')->checkboxList(ArrayHelper::map($subjects, 'id', 'name')) ?> <div class="form-group"> <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> </div> <?php ActiveForm::end(); ?> </div> 

    1 answer 1

     <? //Модель class Teachers extends ActiveRecord { //Сюда будем получать идентификаторы Subjects //Не забудьте включить это свойство в rules() public $subjectsInput = []; public static function tableName() { return 'teachers'; } public function getSubjectsId() { //Проиндексировал результат return $this->hasMany(Subjects::className(), ['id' => 'subjects_id']) ->viaTable('teachers_subjects', ['teachers_id' => 'id'])->indexBy('id'); } } //Метод actionCreate контроллера TeachersController //actionUpdate сделайте аналогично. Я прокомментировал что необходимо для update public function actionCreate() { $model = new Teachers(); //Только для actionUpdate надо установить начальные значения для subjectsInput $model->subjectsInput = array_keys($model->subjectsId); $subjects = Subjects::find()->all(); $department = new Departments(); $facultiesWithDepartment = $department->find()->with('facultyId')->asArray()->all(); $posts = Posts::find()->all(); if ($model->load(Yii::$app->request->post()) && $model->save()) { $currentSubjects = $model->subjectsId; //Связанные с моделью предметы $newSubjects = Subjects::find()->where(['id' => $model->subjectsInput])->indexBy('id')->all(); //Новые (переданные через форму) предметы //Далее будет универсальный код. Для метода actionCreate не нужно использовать $keysToDelete //потому что ничего не удаляется //Идентификаторы предметов которые необходимо создать получаются как разница //между связанными и переданными предметами $keysToCreate = array_diff(array_keys($newSubjects), array_keys($currentSubjects)); //Соответственно удалить - наоборот (используйте только для actionUpdate) $keysToDelete = array_diff(array_keys($currentSubjects), array_keys($newSubjects)); //Создать связи foreach ($keysToCreate as $key) { $model->link('subjectsId', $newSubjects[$key]); } //Удалить связи (используйте только для actionUpdate) foreach ($keysToCreate as $key) { $model->unlink('subjectsId', $currentSubjects[$key]); } return $this->redirect(['view', 'id' => $model->id]); } else { return $this->render('create', [ 'model' => $model, 'facultiesWithDepartment' => $facultiesWithDepartment, 'posts' => $posts, 'subjects' => $subjects ]); } } //Часть формы <?= $form->field($model, 'subjectsInput')->checkboxList(ArrayHelper::map($subjects, 'id', 'name')) ?>