Как написать действия контроллера для работы с Nested Set - vorst.ru

Контроллер


элементарные, но достаточные действия над деревом Nested Set

Определение элементарных действий для работы со структурой Nested Set. Добавление нового узла, изменение заголовка, удаление узда.

Контроллер

элементарные, но достаточные действия над деревом Nested Set

Все необходимые методы, для управления деревом Nested Set уже определены в расширении.

Поэтому изменения в стандартном контроллере совсем небольшие. Нужно, например, вместо стандартного метода save() модели использовать метод prependTo() расширения, а вместо delete(), deleteWithChildren().

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

Но, по порядку.


Начнем с добавления новой рубрики. Из формы ввода поступают всего два поля данных - $parent_node и $name. Именно значение поля $parent_node позволяет правильно заполнить поля lft, rgt новой записи и делается это с помощью метода prependTo() расширения.

А все действие выглядит следующим образом:

public function actionCreate()
{
  $model = new Rubric();
  if ($model->load(Yii::$app->request->post())) {
    if($model->prependTo($this->findModel($model->parent_node)))
      return $this->redirect(['index']);
  } else {
    return $this->render('create', [
      'model' => $model,
    ]);
  }
}

При редактировании важно учесть возможность изменения родителя.

public function actionUpdate($id)
{
  $model = $this->findModel($id);
  // $parent_node is empty, so it must be set
  if($one = $model->parents(1)->one())
  {
    $model->parent_node = $one->id;
    if ($model->load(Yii::$app->request->post()) && $model->save()) {
      return $this->redirect(['index']);
...

При удалении рубрики необходимо заменить в статьях соответствующие ссылки на рубрику "Root". Эту же операцию нужно выполнить для всех потомков, так как и они будут удалены при вызове метода deleteWithChildren().

      $node = $this->findModel($id);
      // find all node childrens
      $childrens = $node->children()->all();
      $node->deleteWithChildren();
      // update deleted rubrics to 1 in all posts with rubrics are $id or $childrens ID
      $ids = $id;
      foreach($childrens as $node)
        $ids .= ',' . $node->id;
      Post::updateAll(['rubric' => 1], 'rubric IN (' . $ids . ')');

Действие index это стандартный GridView.

Для начала работы с рубрикатором нам не хватает еще пары вещей. Во-первых нужно определить поле rubric в модели Post и во-вторых нужен виджет, который позволит выбирать нужную рубрику для просмотра всех, относящихся к рубрике статей. Но об этом, как обычно, в следующей статье.

Заключение

В контроллере рубрикатора обязательно использовать методы, предусмотренные расширением Nested Sets для модификации дерева.

Оставьте комментарий

Только авторизованные посетители могут оставлять комментарии. Пожалуйста, войдите или пройдите регистрацию.