PHP / MySQL - построение иерархии навигационного меню - PullRequest
4 голосов
/ 25 января 2009

Итак, итоговое меню будет выглядеть примерно так:

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

Как бы я показывал? Я предполагаю, что это будет включать в себя сохранение всех элементов в многомерный массив, а затем как-то проходить через него ...

Ответы [ 5 ]

8 голосов
/ 25 января 2009

Иерархические данные несколько раздражают в реляционной базе данных (исключая Oracle, у которого есть операторы в START WITH/CONNECT BY для решения этой проблемы). В основном две модели : список смежности и вложенные множества.

Вы выбрали наборы смежности, что я обычно и делаю. Это гораздо проще изменить, чем модель с вложенным набором, хотя модель с вложенным набором может быть получена в правильном порядке в одном запросе. Списки смежности быть не может. Вам нужно будет построить промежуточную структуру данных (дерево) и затем преобразовать ее в список.

Что бы я сделал (и на самом деле сделал недавно):

  • выбрать все содержимое меню в одном запросе, упорядоченное по родительскому идентификатору;
  • Построить дерево структуры меню, используя ассоциативные массивы или классы / объекты;
  • Пройдите по этому дереву, чтобы создать вложенные неупорядоченные списки; и
  • Используйте плагин jQuery, например Superfish , чтобы превратить этот список в меню.

Вы строите что-то вроде этого:

$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 для генерации массива меню достаточно прост, но немного сложен для решения. Вы используете рекурсивную функцию обхода дерева, которая создает разметку вложенного списка HTML, но оставит ее реализацию в качестве упражнения для читателя. :)

7 голосов
/ 25 января 2009

Работа со структурой данных, которая у вас есть, часто будет включать в себя рекурсию или несколько запросов для построения дерева.

Рассматривали ли вы другие способы хранения иерархии? Ознакомьтесь с измененным обходом предварительного заказа - вот хорошая PHP-статья об этом .

2 голосов
/ 25 января 2009

Способ хранения иерархических данных не так эффективен, как вы могли бы пожелать. Я прочитал статью Управление иерархическими данными в MySQL несколько лет назад и с тех пор нашел ее как лучшее решение для управления данными на основе иерархии в SQL. Следующим лучшим преимуществом является то, что я считаю, что вы можете получить все дерево одним запросом.

1 голос
/ 30 июля 2010

Я только что опубликовал в похожем вопросе свой собственный подход к преобразованию иерархических данных MySQL (список смежности) в меню (HTML)

Он не использует рекурсию. И для этого требуется один запрос к базе данных.

Подробнее на

https://stackoverflow.com/questions/2871861#3368622

Спасибо.

0 голосов
/ 25 января 2009

Другой простой способ создания иерархии, если вы не хотите использовать вложенные наборы, - это использование простой текстовой строки в начале.

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

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

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

...