Yii2复选框列表分解成类别(嵌套集)


Yii2 checkboxlist broken down into categories (nested sets)

我似乎在创建一个允许复选框和嵌套集一起工作的表单输入时遇到了一些麻烦。

我想做的,就是像bookbub做的那样:https://i.stack.imgur.com/XHmD0.jpg

现在在我的数据库中,我有它的结构如下:

Category table
    - id
    - name
    - parent_id

基本上,我的想法是在_form上显示所有具有parent_id为空的标题(没有复选框),以及在适当标题下具有parent_id作为复选框的所有内容。

然而,我能得到的唯一解决方案,这似乎不允许我有复选框已经被选中,如果我们更新用户的首选项。然而,它确实显示了我想要的东西。以下是目前为止的内容:

ProfileReader的(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']);
}

有没有人有任何线索我怎么才能使这个工作?这在activeform的Yii2中可能吗?

好吧,几个小时后我终于弄明白了。在这里张贴我的结果代码,以便它可以帮助其他人。别让我解释,我自己也不完全明白: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模型(必须添加一个变量):

公共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>']);
}
?>