Задать вопрос

Как отрисовать дерево Nested sets имея все записи?

ДД.
Использую https://github.com/creocoder/yii2-nested-sets
Если через рекурсию то получается легко отрисовать запрашивая потомков друг за другом с ограничением "depth = 1", но выходит кучу запросов.
Хотелось бы получить все записи одним запросом и как-то их отрисовать, обычно видел что используют parent_id, но тут такого нет.

Или можно как-то сделать связи, чтоб 2-3 запросами он построил связи? Сейчас под 30-40 запросов, чтоб отрисовать все.

Или может отказаться от этого, но тогда что лучше? Нужно сделать список разделов из 3-4 уровней с 50-60 элементов
  • Вопрос задан
  • 2252 просмотра
Подписаться 2 Оценить Комментировать
Решения вопроса 2
webinar
@webinar Куратор тега Yii
Учим yii: https://youtu.be/-WRMlGHLgRg
$myModel = MyModel::find()->orderBy('lft')->all();
Далее рекурсия в php. 1 запрос. Вся хитрость в сортировке по lft. Тогда у Вас уже есть правильная упорядоченная структура, остается ей только вложенность сделать базируясь на depth.
Как вариант можете тут глянуть:
https://github.com/yiiext/nested-set-behavior/blob...
там внизу самом пример php есть. Он для yii1, но по сути все так же
Ответ написан
@Arik Автор вопроса
Остановился на таком обходе
$f = function ($f, $categories, $lft = 0, $rgt = null, $depth = 1) {

    if (!$categories) {
        return '';
    }
    $result = '';

    foreach ($categories as $k => $category) {

        $catId = $category->id;
        $catLft = $category->lft;
        $catRgt = $category->rgt;
        $catDepth = $category->depth;

        if ($catDepth != $depth || $catLft < $lft + 1 || ($rgt !== null && $catRgt > $rgt)) {
            continue;
        }

        $result .= $f($f, $categories, $catLft, $catRgt, $catDepth + 1);
    }

    return $result;
};
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 4
ThunderCat
@ThunderCat
{PHP, MySql, HTML, JS, CSS} developer
вроде ничего необычного, делаете запрос и выбираете все записи, затем на пхп делаете рекурсивную функцию и строите дерево, тут вместо parent_id насколько я понял используется указание lft - элемент слева - видимо родитель, и rgt - элемент потомок. Функция ищется поисковиком за минуту, по запросу рекурсия дерево нестед сетс.
Ответ написан
Комментировать
slo_nik
@slo_nik Куратор тега Yii
Доброе утро.
В ActiveRecord можно делать связи с одной модели на другую. Если Вы об этом, то вот здесь смотрите (Работа со связными данными).
Ответ написан
Комментировать
PaulZi
@PaulZi
Если интересно в моём nested sets расширении есть метод populateTree(), который как раз позволяет запросить из базы одним запросом потомков и актуализировать их связи.
Ответ написан
@Aleksei-22
Вот такая функция возвращает всё дерево в виде многомерного массива с добавлением parent_id каждому элементу для удобства. Работает с любым количеством деревьев и любой степенью вложенности.
Далее из этого массива можно что угодно нарисовать.
Если в вашей таблице используется под уровни 'depth' вместо 'lvl', поменяйте
$l = $node['lvl']; на $l = $node['depth']; Соответственно также $r = $node['root']; на $r = $node['tree'], если вместо 'root' в базе 'tree'.
Если таблица без использования множества деревьев, тогда $r = 1;
Используется один запрос к базе. Перебор уровня вложенности можно менять с помощью $level.
$category = CategoryMenu::find()->orderBy('root, lft')->indexBy('id')->asArray()->all();

function getTree($category, $level = 0) {
   $tree = []; $_id = [];
   foreach ($category as $id=>&$node) {
      $l = $node['lvl']; $p = $l-1; $r = $node['root']; $_id[$r][$l] = $id;
      if ($l == $level) {
         $tree[$id] = &$node;
      } elseif ($l > $level) {
         $category[$_id[$r][$p]]['childs'][$id] = &$node;
         $node['parent_id'] = $category[$_id[$r][$p]]['id'];
      }
   }
   return $tree;
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы