Флажок Yii2 с разбивкой по категориям (вложенные множества)

Кажется, у меня возникли проблемы с созданием входных данных формы, которые позволяют флажкам и вложенным наборам работать вместе.

То, что я хотел бы, это что-то вроде того, что делает bookbub:
http://i.imgur.com/PfpgSf5.jpg

Прямо сейчас в моей базе данных она имеет следующую структуру:

Category table
- id
- name
- parent_id

По сути, моя идея состоит в том, чтобы отобразить все в _form, у которого parent_id имеет значение null в качестве заголовка (без флажка), и все, у кого parent_id установлен в качестве флажка под соответствующим заголовком.

Тем не менее, единственное решение, которое я могу найти, это не позволяет мне иметь уже отмеченные флажки, если мы обновляем пользовательские настройки. Это, однако, отображает вещи именно так, как я хотел бы. Вот что у меня так далеко:

ProfileReader’s (ProfileReader — моя модель, которая расширяет возможности пользователей хранить свои предпочтения) _form:

<?php
$primaryCategories = (new Category)->getPrimaryCategories();
//$selectedCategories = yii\helpers\ArrayHelper::map($model->categories, 'id', 'name');
foreach ($primaryCategories as $pc) {
echo '<p>'.$pc->name.'</p>';
if ($pc->subCategories) {

//the following never fully worked. It doesn't automatically check the boxes for relations that
//are already setup. You need to somehow use $model->categories[#] and 'id' for that to work
//echo $form->field($model->categories[#], 'id')->label(false)
echo $form->field($pc, 'subCategories[' . $pc->id . '][]')->label(false)
->checkboxList(yii\helpers\ArrayHelper::map($pc->subCategories, 'id', 'name'),
['separator' => '<p>']);
}
}
?>

ProfileReaderController:

public function actionUpdate()
{
$model = $this->findModel(\Yii::$app->user->identity->id);
if ($model == null) {
$model = new ProfileReader();
$model->user_id = \Yii::$app->user->identity->id;
}

if ($model->load(Yii::$app->request->post()) && $model->save()) {

//link the categories to the pen name
$categories = Yii::$app->request->post()['Category']['subCategories'];
$model->unlinkAll('categories', true);
foreach ($categories as $category) {
if ($category)
foreach ($category as $c) {
$c = (new Category)->findOne($c);
$model->link('categories', $c);
}
}

return $this->redirect(['update']);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}

ProfileReader:

public function getCategories()
{
return $this->hasMany(Category::className(), ['id' => 'category_id'])
->viaTable('user_category', ['user_id' => 'user_id']);
}

Кто-нибудь знает, как я могу сделать эту работу? Возможно ли это даже в Yii2 с activeform?

0

Решение

Хорошо, через много часов я наконец-то понял это. Размещение моего результирующего кода здесь, чтобы он мог помочь кому-то еще. Не проси меня объяснить это, так как я сам не до конца понимаю: P

Также может быть хорошей идеей провести некоторое тестирование на нем, прежде чем бросать его в живую среду, я еще этого не делал.

обновить действие:

/**
* Updates an existing ProfileReader model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param integer $id
* @return mixed
*/
public function actionUpdate()
{
$model = $this->findModel(\Yii::$app->user->identity->id);
if ($model == null) {
$model = new ProfileReader();
$model->user_id = \Yii::$app->user->identity->id;
}

if ($model->load(Yii::$app->request->post()) && $model->save()) {

//unlink the categories first to avoid duplicates
$model->unlinkAll('categories', true);
//link the categories to the pen name
foreach ($model->categoriesArray as $pc) {
if ($pc) {
foreach ($pc as $sc) {
$sc = (new Category)->findOne($sc);
$model->link('categories', $sc);
}
}
}

return $this->redirect(['update']);
} else {

//get the categories and separate them into groups based on parent_id
foreach ($model->categories as $c) {
$model->categoriesArray[$c->parent_id][] = $c;
}

return $this->render('update', [
'model' => $model,
]);
}
}

Модель ProfileReader (пришлось добавить переменную):

public $ CategoriesArray;

_form:

<label class="control-label">Categories</label>
<?php
$allCategories = (new Category)->getOrderedCategories();
foreach ($allCategories as $pc) {
echo '<p>'.$pc['name'].'</p>';
echo $form->field($model, 'categoriesArray['.$pc['id'].'][]')->label(false)
->checkboxList(yii\helpers\ArrayHelper::map($pc['subCategories'], 'id', 'name'),
['separator' => '<p>']);
}
?>
0

Другие решения

Других решений пока нет …