Формирование древовидного меню с сортировкой

kamwork

Новичок
Всем привет!

Пересмотрел много тем, но не нашел вариаций с сортировкой.

У меня таблица выглядит так: id, parent_id, sort

При этом sort формируется каждый раз от 1 на каждом уровне вложенности.

Получается как то так - http://my.jetscreenshot.com/3532/20140423-jlok-23kb.jpg

Не могу сообразить, как это все за 1 запрос к БД вывести так, что бы можно было разнести по уровням вложенности и отсортировать :(
 

Фанат

oncle terrible
Команда форума
так тебе ибез сортировки никто одним запросом не предложит
используй materialized path
 

kamwork

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


PHP:
 $result  = mysql_query("SELECT `id`, `parent_id`, `label`
                          FROM `menu`
                          ORDER BY `sort` ASC "
                        );

  $i = 0;
  while($row = mysql_fetch_assoc($result)) {    
    $rows[$i] = $row;
    $i++;
  }

/**
* Возвращает html код дерева
* @param  array    $tree - массив в формате array(array('name' => .., 'id' => .., 'pid' => ..), array(..))
* @param  integer  $pid - id родителя
*/
function get_tree($tree, $pid)
{
    $html = '';
    foreach ($tree as $row)
    {
        if ($row['parent_id'] == $pid)
        {
          $html .= '<li class="dd-item dd3-item" data-id="'.$row['id'].'">';
          $html .= '<div class="dd-handle dd3-handle">Drag</div><div class="dd3-content">'.$row['label'].'</div>';
          $html .= '    ' . get_tree($tree, $row['id']);
          $html .= '</li>';
        }
    }
    return $html ? '<ol class="dd-list">' . $html . '</ol>' . "\n" : '';
}


   echo get_tree($rows, 0);
 

WMix

герр M:)ller
Партнер клуба
kamwork, решив эту проблему ты забыл про другую: обрисовать всех деток до 3го уровня, ветки id=42, у дерева, количество элементов которого, далеко уходит за десятки тысяч. и как только задумаешься над этим, обрати внимание на первые 2 ответа.
 

kamwork

Новичок
Такс.. подкорректировал БД, добавил path, верно ли я уловил суть материализированного пути?




Поле sort сделал со сквозной нумерацией.

Но склоняюсь к тому, что прошлай версия, где нумерация расчитывалась в пределах одного уровня, была лучше.
 

WMix

герр M:)ller
Партнер клуба
я всеже посоветывал бы еще немного поломать голову и увлечься Nested Sets, если поймешь, то поле sort вообще больше не понадобится. но как бы там нибыло удобно иметь еще одно поле - level.

при сквозной сортировке, после каждого добавления, придеться обновлять все дерево, после вставленной ветки.
 
Последнее редактирование:

kamwork

Новичок
я всеже посоветывал бы еще немного поломать голову и увлечься Nested Sets, если поймешь, то поле sort вообще больше не понадобится. но как бы там нибыло удобно иметь еще одно поле - level.

при сквозной сортировке, после каждого добавления, придеться обновлять все дерево, после вставленной ветки.
Всем спасибо за пендали :)

Уровни вложенности добавил. Получилось так:



Читал за Nested Sets, но пока не осилил. Наверное позже вернусь к этому вопросу.


Пока у меня кол-во категорий вряд ли выйдет за 300-500 штук, думаю не страшно будет целиком пересохранять.

Возвращаясь к вопросу вытяжки всего дерева и построения в иерархии, функция, что я описал в первом посте годна или нужно, что то иное искать?
 

WMix

герр M:)ller
Партнер клуба
на 300-500, даже не заморачивайся, твое решение годное, оно конечно рекурсия со сложностью O(N²),
ну да надеюсь будет правильный проджектик, и вернешся к этой проблемке.
а с путем и уровнем можно творить чудеса.
 

kamwork

Новичок
на 300-500, даже не заморачивайся, твое решение годное, оно конечно рекурсия со сложностью O(N²),
ну да надеюсь будет правильный проджектик, и вернешся к этой проблемке.
а с путем и уровнем можно творить чудеса.
Благодарю! Задышалось легче :)
 

флоппик

promotor fidei
Команда форума
Партнер клуба
на 300-500, даже не заморачивайся, твое решение годное, оно конечно рекурсия со сложностью O(N²),
ну да надеюсь будет правильный проджектик, и вернешся к этой проблемке.
а с путем и уровнем можно творить чудеса.
там и глубина не особо нужна, на самом деле, она известна из количества элементов пути. А вот разделитель надо сделать запятой, тогда в мускуле можно использовать FIND_IN_SET
 

WMix

герр M:)ller
Партнер клуба
я понимаю что глубина в пути неявно присутствует, но вот как добраться не соображу.
 

WMix

герр M:)ller
Партнер клуба
Код:
LENGTH('1,2,3,4,5') - LENGTH(REPLACE('1,2,3,4,5', ',', ''))
ну так... :) можно конечно
 
Сверху