Как подключить расширение Nested Set - vorst.ru

Nested Set


Подключение расширения

Создание рубрикатора с помощью структуры данных Nested Set. Вложенные рубрики с неограниченным количеством уровней.

Nested Set

Подключение расширения

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

Поведение выполняет работу по добавлению новых элементов в дерево, поиск всех подчиненных элементов для данного узла, удаление узла. И многое другое, что может быть использовано, например, при работе с каталогами товаров.

Наши задачи проще и сводятся к следующему:

  1. Управление рубрикатором - добавление и удаление рубрик, редактирование, отображение списка рубрик для визуального контроля.
  2. Закрепление статьи за рубрикой.
  3. Вывод списка рубрик для выбора нужной рубрики.

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


Cоздадим таблицу, которая будет хранить дерево рубрик и введем обязательную корневую рубрику.

CREATE TABLE tbl_rubric (
  id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  lft INT(11) NOT NULL,
  rgt INT(11) NOT NULL,
  level INT(11) NOT NULL,
  name VARCHAR(50) NOT NULL,
  KEY lft (lft),
  KEY rgt (rgt),
  KEY level (level)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO tbl_rubric (id, lft, rgt, level, name) values(1, 1, 2, 1, 'Без рубрики')

Установим расширение Nested Set.

Создадим модель common\models\Rubric.php, подключив расширение и определив два служебных поля значение которых будет объяснено позже.

namespace common\models;
use creocoder\nestedsets\NestedSetsBehavior;
use yii\db\ActiveRecord;
class Rubric extends ActiveRecord
{
  public $parent_node; // the parent node for just added
  public $post_count; // posts count in a rubric
  ...
  public function behaviors()
  {
    return [
      'tree' => [
        'class' => NestedSetsBehavior::className(),
          'depthAttribute' => 'level',
      ],
    ];
  }
  ...

И напишем пару методов.

Первый из которых будем использовать для вывода названий рубрик. Для отражения уровня вложенности будем делать отступы. Формирование отступов зависит от вывода. Метод формирования будет разным для выпадающего списка и просто вывода в блоке.

  public function getPrettyName($dropdown = false)
  {
    return $dropdown 
      ? str_repeat('-', ($this->level - 1) * 2) . ' ' . $this->name
      : '<span style="margin-left:' . (($this->level - 2) * 20) . 'px;">' . 
        $this->name . '</span>';
  }

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

Цели добавления новой рубрики и служит одно из дополнительных полей модели - $parent_node. Добавляя новую рубрику мы должны определить ее предка. Именно за ним и будет вставлен "новичок".

Итак, метод items()

  public function items($rootTitle = null)
  {
    if(!$rootTitle) 
      $rootTitle = \Yii::t('app', 'Root');
    $a = [];
    $a[1] = $rootTitle;
    foreach(Rubric::find()->where('id>1')->orderBy('lft ASC')->all() as $node)
      $a[$node->id] = $node->getPrettyName(true);
    return $a;
}

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

Заключение

Для создания рубрикатора не обязательно вникать в детали работы программы-расширения, которая выполняет всю основную работу.

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