Blog. Just Blog

Создание древовидного списка из массива

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Web-мастеру и не только | Автор: ManHunter
Еще одна из часто встречающихся задач при разработке сайтов - создание многоуровневых древовидных списков. Отдельные элементы списков хранятся в массиве и объединяются между собой через связку полей "ID элемента" - "Родительский элемент". Это могут быть выпадающие меню с несколькими уровнями субменю, каталоги товаров по категориям, карты сайта и т.п. Попробуем описать трехуровневое вложенное меню. Для этого зададим массив вручную, а в реальной ситуации он может быть, например, получен из базы. Количество уровней вложенности может быть произвольным, три уровня выбраны исключительно для примера.
  1. // Построение из массива древовидного списка без использования рекурсии
  2. $menu=array(
  3.      1=>array('name'=>'Овощи''parent'=>0),
  4.          6=>array('name'=>'Капуста''parent'=>1),
  5.          7=>array('name'=>'Помидоры''parent'=>1),
  6.          9=>array('name'=>'Салат''parent'=>1),
  7.              18=>array('name'=>'Китайский салат''parent'=>9),
  8.          12=>array('name'=>'Тыква''parent'=>1),
  9.          16=>array('name'=>'Редиска''parent'=>1),
  10.      2=>array('name'=>'Фрукты''parent'=>0),
  11.          13=>array('name'=>'Бананы''parent'=>2),
  12.          14=>array('name'=>'Ягоды''parent'=>2),
  13.              19=>array('name'=>'Арбуз''parent'=>14),
  14.              20=>array('name'=>'Клубника''parent'=>14),
  15.      3=>array('name'=>'Животные''parent'=>0),
  16.      4=>array('name'=>'Растения''parent'=>0),
  17.          8=>array('name'=>'Конопля''parent'=>4),
  18.          11=>array('name'=>'Мак''parent'=>4),
  19.          17=>array('name'=>'Сахарный тростник''parent'=>4),
  20.      5=>array('name'=>'Насекомые''parent'=>0),
  21.          10=>array('name'=>'Тараканы''parent'=>5),
  22. );
В parent прописан ID родительского элемента для каждого субменю, главное меню (первый уровень) имеет parent=0. Теперь нам надо из этого линейного массива сделать древовидный согласно связям родительских и дочерних элементов. Обычно для этого используется решения с применением рекурсии или же требуется, чтобы исходный массив был специальным образом отсортирован. Но вполне можно обойтись таким вот элегантным решением с использованием ссылок:
  1. // Построение дерева за один проход
  2. foreach($menu as $menu_id=>$data) {
  3.     // Прописать в родительском узле ссылку на пункт меню
  4.     $menu[$data['parent']]['child'][$menu_id]=&$menu[$menu_id];
  5. }
  6.  
  7. // Готовый массив находится в $menu[0]['child']
  8. $sorted_menu=(array)$menu[0]['child'];
Единственное условие, чтобы исходный массив не содержал кольцевых замыканий, это когда родительский элемент ссылается в качестве своего родителя на свой дочерний элемент. Других ограничений нет, массив может быть как угодно отсортирован и иметь "дыры" в нумерации ID.

Массив преобразован в древовидную структуру, теперь его можно вывести на экран или вставить в шаблон сайта.
  1. echo '<ul>';
  2. foreach($sorted_menu as $top_menu) {
  3.     // Меню верхнего уровня
  4.     echo '<li>'.$top_menu['name'];
  5.     if (count($top_menu['child'])) {
  6.         // Субменю второго уровня
  7.         echo '<ul>';
  8.         foreach($top_menu['child'] as $sub_menu) {
  9.             echo '<li>'.$sub_menu['name'];
  10.             if (count($sub_menu['child'])) {
  11.                 // Субменю третьего уровня
  12.                 echo '<ul>';
  13.                 foreach($sub_menu['child'] as $subsub_menu) {
  14.                     echo '<li>'.$subsub_menu['name'].'</li>';
  15.                 }
  16.                 echo '</ul>';
  17.             }
  18.             echo '</li>';
  19.         }
  20.         echo '</ul>';
  21.     }
  22.     echo '</li>';
  23. }
  24. echo '</ul>';
Если уровень вложенности задан жестко, как в нашем случае, то можно обойтись линейным кодом с несколькими вложенными циклами. А вот для отрисовки вложенных меню или списков произвольной вложенности уже придется использовать рекурсивные функции. Как обычно, вариант решения зависит от конкретной задачи.

Поделиться ссылкой ВКонтакте
Просмотров: 11243 | Комментариев: 11

Метки: PHP
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
THomZone (29.09.2015 в 09:25):
Спасибо огромное
fif (17.04.2015 в 10:39):
Помогите приспособить это решение для вывода списка категорий с дочками с постраничной навигацией.
ManHunter (07.04.2015 в 11:37):
Ахуеть! В детском садике выходной что ли? Скрипткиддисов отпустили домой мамкину сиську пососать? Иди нахуй, уебок.
sas (07.04.2015 в 10:14):
<img src='javascript:alert()'>
Иван (03.07.2013 в 11:46):
Спасибо за простоту решения.
[p0-[ (15.03.2013 в 23:54):
[-[[
Droid (26.08.2011 в 02:10):
Можете показать версию где массив данных берётся из БД ?
Александр (09.08.2011 в 14:05):
Мне лично больше нравиться рекурсия ) Просто и компактно. Да и редактировать проще ее. Скажем, если будет необходимо прописать не просто тег <li>, а <li class="my_li">, то надо будет три раза исправлять вместо одного ) Либо пользоваться Ctrl+F )
eGo (07.08.2011 в 07:40):
А я уже тут размечтался, думал появился тот самый гуру что придумал функцию для нерекурсивного вывода массива со структурой adjacency list
Megabyte (21.05.2011 в 00:13):
Огромное человеческое спасибо!
prohozhiy (03.05.2011 в 11:24):
4=>array('name'=>'Растения', 'parent'=>0),
         8=>array('name'=>'Конопля', 'parent'=>4),
         11=>array('name'=>'Мак', 'parent'=>4)
Растения похоже не совсем случайно выбирались :-)

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 1.46 сек. / MySQL: 2 (0.0273 сек.) / Память: 4.5 Mb
Наверх