voskobovich / yii2-many-to-many-behavior

This behavior soon will be DEPRECATED. See the link:

Home Page:https://github.com/voskobovich/yii2-linker-behavior

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Сохраняет не все связи из формы в таблицу

zhe17065564 opened this issue · comments

Здравствуйте. Столкнулся с такой проблемой, что поведение many-to-many при создании записи, в моем случае публикации, сохраняется связь только с последнего поля формы , а их 4 различных типа в форме. В связующую таблицу сохраняет только id публикации и id последнего типа соавторов, остальные пустые(то есть null). Поведение вообще поддерживает сохранение нескольких связей в одну таблицу, чтобы глобально хранить "набором" связи или все же надо переписывать логику? Пробовал разносить по разным таблицам - тогда работает и сохраняет все связи, но к-во запросов к БД возрастает, чего хотелось бы избежать. Может подскажете хотя бы вектор куда двигаться - изменять логику поведения или же в контроллере дополнительно обрабатывать все входящие данные и тогда передавать в save() ? Вот собственно код формы - там всё подгружает всё работает:

` <?= $form->field($model, 'staff_ids')->widget(Select2::classname(), [
        'model' => $model,
        'attribute' => 'staff_ids',

           'data'=>Staff::listAll(),
           'options' => [
                'placeholder' => '-Выберите автора-',
                'multiple' => true,
            ],
            'pluginOptions' => [
                'tags' => true,
            ],
          ])->label('Авторы сотрудники')

    ?>

<?= $form->field($model, 'student_ids')->widget(Select2::classname(), [
    'model' => $model,
    'attribute' => 'student_ids',

       'data'=>Student::listAll(),
       'options' => [
        'placeholder' => '-Выберите соавтора-',
            'multiple' => true,
        ],
        'pluginOptions' => [
            'tags' => true,
        ],
      ])->label('Соавторы студенты')

?>

<?= $form->field($model, 'oi_ids')->widget(Select2::classname(), [
    'model' => $model,
    'attribute' => 'oi_ids',

       'data'=>Oi::listAll(),
       'options' => [
            'placeholder' => '-Выберите соавтора-',
            'multiple' => true,
        ],
        'pluginOptions' => [
            'tags' => true,
        ],
      ])->label('Соавторы других ВУЗов')

?>

<?= $form->field($model, 'fi_ids')->widget(Select2::classname(), [
    'model' => $model,
    'attribute' => 'fi_ids',

       'data'=>Fi::listAll(),
       'options' => [
            'placeholder' => '-Выберите соавтора-',
            'multiple' => true,
        ],
        'pluginOptions' => [
            'tags' => true,
        ],
      ])->label('Соавторы зарубежных ВУЗов')

?>

<?= $form->field($model,'user_id')->hiddenInput(['value' => Yii::$app->user->id]);?>`

А вот код модели:

`class Publications extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%ssu_publications}}';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['job_title', 'types', 'indexing', 'status', 'country', 'output_data', 'published_sumdu', 'student_publication', 'user_id'], 'required'],
            [['job_title', 'types', 'indexing', 'status', 'country', 'output_data', 'published_sumdu', 'student_publication'], 'string'],
            [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
            [['staff_ids', 'student_ids', 'oi_ids', 'fi_ids'], 'each', 'rule' => ['integer']],
        ];
    }
/**
 * @inheritdoc
 */
public function behaviors()
{
    return [
            [
             'class' => \voskobovich\behaviors\ManyToManyBehavior::className(),
             'relations' => [
                'staff_ids' =>'staff',
                'student_ids' => 'student', 
                 'oi_ids' =>'oi',
                'fi_ids' =>'fi',
                ],
            ],
        ];
}

/**
 * @inheritdoc
 */
public function attributeLabels()
{
    return [
        'id' => Yii::t('app', 'ID'),
        'job_title' => Yii::t('app', 'Название работы'),
        'types' => Yii::t('app', 'Тип'),
        'indexing' => Yii::t('app', 'Индексация в БД Scope'),
        'status' => Yii::t('app', 'Статус'),
        'country' => Yii::t('app', 'Страна'),
        'output_data' => Yii::t('app', 'Исходные данные'),
        'published_sumdu' => Yii::t('app', 'Публикация вуза'),
        'student_publication' => Yii::t('app', 'Публикация студента'),
        'user_id' => Yii::t('app', 'Пользователь ID'),
    ];
}

/**
 * @return \yii\db\ActiveQuery
 */
public function getUser()
{
    return $this->hasOne(User::className(), ['id' => 'user_id']);
}

 public function getStaff()
{
    return $this->hasMany(Staff::className(), ['id' => 'staff_id'])
         ->viaTable('{{%ssu_composite}}', ['publication_id' => 'id']);
}

public function getStudent()
{
    return $this->hasMany(Student::className(), ['id' => 'student_id'])
         ->viaTable('{{%ssu_composite}}', ['publication_id' => 'id']);
}

public function getOi()
{
    return $this->hasMany(Oi::className(), ['id' => 'oi_id'])
         ->viaTable('{{%ssu_composite}}', ['publication_id' => 'id']);
}

public function getFi()
{
    return $this->hasMany(Fi::className(), ['id' => 'fi_id'])
         ->viaTable('{{%ssu_composite}}', ['publication_id' => 'id']);
}



/**
 * @inheritdoc
 * @return PublicationsQuery the active query used by this AR class.
 */
public static function find()
{
    return new PublicationsQuery(get_called_class());
}

}`

@zhe17065564 с такой логикой как у вас работать не будет. Если посмотрите в код, то увидите, что перед записью связей из связующей таблицы все удаляется и записывается заново.
Я не могу знать тонкости вашей архитектуры БД, но лучше для организации каждой связи делать отдельную таблицу - это правильно. Почитайте еще подробно про организацию связей много-ко-многим, и вы поймете о чем я говорю.
То есть плохо хранить все в одной таблице ssu_composite, а нужно сделать 4 отдельные. На количество запросов к БД это никак не должно повлиять.

Но если вы не захотите переделывать, тогда вам подойдет мое новое поведение Yii2 Linker Behavior в котором вы можете использовать ManyToManySmartUpdater. Он не удаляет связи, а ищет разницу и вносит ее в таблицу. Это требует больше запросов к БД, но за-то не перезаписывает все связи.

Прошу прощения за поздний ответ. Не получал писем от гитхаба:(