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

时间:2015-08-07 14:46:56

标签: php yii2 checkboxlist nested-sets active-form

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

我想要的是与bookbub完全相同的东西: http://i.imgur.com/PfpgSf5.jpg

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

Category table
    - id
    - name
    - parent_id

基本上,我的想法是在_form上显示所有内容,其中parent_id为null作为标题(无复选框)以及将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']);
}

有没有人知道如何让这项工作成功?甚至可以在Yii2中使用activeform吗?

1 个答案:

答案 0 :(得分: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>']);
}
?>