Сохранение и валидация relations в yii2 через формы — как избежать дублирования атрибутов в форме?

У меня есть модель student (id, name, school_id) и модель school (id, name, ...)
Получается связь school has many students
student принадлежит одной школе всегда.
class School extends \yii\db\ActiveRecord
{
/*.....*/
	public function getStudents()
	{
		return $this->hasMany(Student::className(), ['school_id' => 'id']);
	}
/*.....*/
}


При создании школы я хочу вывести чекбоксами всех студентов к которым еще не прицеплена школа, казалось бы, это было логично сделать так (в тплке формы для создания модели School):

<?= $form->field($model, 'students')->checkboxList(ArrayHelper::map($allStudents, 'id', 'name')) ?>

(студентов будет мало, поэтому для упрощения говорим про чекбоксы тут)
но когда начинаю писать rules для валидации поля students (ну, например, чтобы ограничить макс кол-во 5 студентов на школу) то вылетает эксепшн tryin to set readonly attribute!

То есть, получается, что relation - это атрибут только для чтения.
Как же мне красиво использовать ActiveForm и валидацию через rules модели School тут?
Придумывать помимо students еще одно поле student_ids, которое по факту не будет существовать в базе, но будет использоваться для прописывания rules в модели школы?
или есть "правильный" путь?

Спасибо!
  • Вопрос задан
  • 8397 просмотров
Решения вопроса 1
restyler
@restyler Автор вопроса
Если для кого-то актуально - я решил вопрос введением дополнительного атрибута selectedStudents у класса School, он в бд не пишется, существует чисто для формы и для валидационных правил.
В afterSave хуке в School мы делаем примерно такое:

$students = Student::find()->where(['id' => $this->selectedStudents])->all();
foreach ($students as $student) {
   $student->school_id = $this->id; // еще можно использовать метод link()
   $student->save();
}


Если подобных дублей атрибутов (students readonly и selectedStudents read/write) хочется избежать любой ценой - надо вводить отдельную модель для формы, чтобы в модели School оставался только relation, а в модели формы уже был атрибут selectedStudents, но это мне кажется лучше приберечь для более сложных кейсов.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@iopull
Программист
/**
     * @return \yii\db\ActiveQuery
     */
    public function getCategories()
    {
        return $this->hasMany(Category::className(), ['id' => 'category_id'])->viaTable(ProductCategory::tableName(), ['product_id' => 'id']);
    }

    /**
     * @param $value
     */
    public function setCategories($value)
    {
        $this->categories = $value;
    }
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы