PHP / MySQL - построение иерархии навигационного меню
Вопрос
Таким образом, итоговое меню будет выглядеть примерно так:
Item B
Item B-1
Item B-1-2
Item B-1-1
Item A
SubItem A-1
SubItem A-2
Item C
На основе следующих записей базы данных:
id menu_title parent_menu_id menu_level weight
1 Item A 0 1 1
2 Item B 0 1 0
3 Item C 0 1 2
4 SubItem A-2 1 2 1
5 Item B-1 2 2 0
6 Item B-1-1 5 3 1
7 SubItem A-1 1 2 0
8 Item B-1-2 5 3 0
Как бы я поступил с отображением? Я предполагаю, что это потребует хранения всех элементов в многомерном массиве, а затем каким-то образом перебирать его...
Решение
Работа со структурой данных, которая у вас есть, часто требует рекурсии или нескольких запросов для построения дерева.
Рассматривали ли вы другие способы хранения иерархии? Ознакомьтесь с измененным обходом предварительного заказа - вот хорошая статья на основе PHP об этом , Р>
Другие советы
Иерархические данные несколько раздражают в базе данных отношений (исключая Oracle, в которой есть операторы в START WITH/CONNECT BY
чтобы справиться с этим).В основном существуют две модели:список смежности и вложенные множества.
Вы выбрали наборы смежности, что я обычно и делаю.Ее гораздо проще изменить, чем модель вложенного набора, хотя модель вложенного набора может быть получена в правильном порядке с помощью одного запроса.Списков смежности быть не может.Вам нужно будет создать промежуточную структуру данных (дерево), а затем преобразовать ее в список.
Что бы я сделал (и фактически сделал недавно), так это:
- выберите все содержимое меню в одном запросе, упорядоченном по родительскому идентификатору;
- Постройте дерево структуры меню, используя ассоциативные массивы или классы / объекты;
- Пройдитесь по этому дереву, чтобы создать вложенные неупорядоченные списки;и
- Используйте подключаемый модуль jQuery, например Суперфиш чтобы превратить этот список в меню.
Вы строите что-то вроде этого:
$menu = array(
array(
'name' => 'Home',
'url' => '/home',
),
array(
'name' => 'Account',
'url' => '/account',
'children' => array(
'name' => 'Profile',
'url' => '/account/profile',
),
),
// etc
);
и преобразуйте это в это:
<ul class="menu">;
<li><a href="/">Home</a></li>
<li><a href="/account">Account Services</a>
<ul>
<li><a href="/account/profile">Profile</a></li>
...
PHP для генерации массива menu на основе достаточно прост, но немного сложен в решении.Вы используете рекурсивную функцию обхода дерева, которая создает разметку вложенного списка HTML, но оставим ее реализацию в качестве упражнения для читателя.:)
Способ хранения иерархических данных не так эффективен, как хотелось бы. Я прочитал статью Управление иерархическими данными в MySQL несколько лет назад и с тех пор нашел его как лучшее решение для управления данными на основе иерархии в SQL. Следующим лучшим преимуществом является то, что я считаю, что вы можете получить все дерево одним запросом.
Я только что опубликовал в аналогичном вопросе свой собственный подход к преобразованию иерархических данных MySQL (список смежности) в меню (HTML)
Это так и есть нет используйте рекурсию.И для этого требуется одиночный запрос к базе данных.
Читайте больше по адресу
https://stackoverflow.com/questions/2871861#3368622
Спасибо.
Другой простой способ создания иерархии, если вы не хотите использовать вложенные наборы, - это использование простой текстовой строки в начале.
Item B
Item B-1
Item B-1-2
Item B-1-1
Item A
SubItem A-1
SubItem A-2
Item C
станет
1 Item B
1.1 Item B1
1.1.1 Item B11
1.1.2 Item B12
2 Item A
2.1 Item A1
2.2 Item B2
3 Item C
Цифра перед каждым элементом может быть сохранена в поле и проанализирована на основе длины (представляющей глубину ее расположения), чтобы рассказать вам все, что вам нужно знать о том, куда она идет.
Я использую иерархии вложенных множеств для более сложных вещей, требующих вычислений, и т. д., но я считаю, что этот подход хорошо себя зарекомендовал