LINUX.ORG.RU

SQL структура хранения для выпадающего меню

 ,


0

1

Пишу своё на православной пишечке =), добрался до вывода всех записей с одной категории подпункта меню.

Структура таблицы категорий в базёнке выглядит так

SELECT * FROM `category`;
+----+--------------+
| id | title        |
+----+--------------+
|  1 | Пункт 1      |
+----+--------------+
|  2 | Пункт 2      |
+----+--------------+

Для организации хранения подпунктов мне необходимо добавить данные

INSERT category (title) VALUES ('Подпункт 2');

Опосля структура той же таблицы будет следующей

SELECT * FROM `category`;
+----+--------------+
| id | title        |
+----+--------------+
|  1 | Пункт 1      |
+----+--------------+
|  2 | Пункт 2      |
+----+--------------+
|  3 | Подпункт 2   |
+----+--------------+

Из HTML должно быть ясным, что я хочу все подпункты запихнуть в выпадающий список Пункта 1.

<nav>
    <ul class="nav">
        <li><a href="#">Пункт 1</a>
            <ul class="subnav">
                <li><a href="#">Подпункт 1</a></li>
                <li><a href="#">Подпункт 2</a></li>
                <li><a href="#">Подпункт 3</a></li>
            </ul>
        </li>
        <li><a href="#">Пункт 2</a>
    </ul>
</nav>

Сопсна сам вопрос. Как сделать запрос на вывод всех подпунктов из пункта 1…? Вангую что хранение подпунктов нужно делать в отдельной таблице и рисовать связи с пунктами. Возможно есть какой-то иной способ?

Уважаемые знатоки прекрасного ЯП PHP (коих не так много), направьте на путь истинный…=)

★★

Последнее исправление: dataman (всего исправлений: 1)

Таблица меню,

ID  PARENT_ID  TITLE
1   NULL       Пункт 1
2   1          Подпункт 1, пункта 1
3   1          Подпункт 2, пункта 1
4   NULL       Пункт 2
5   4          Подпункт 1, пункта 2
6   4          Подпункт 2, пункта 2
ID это понятно что, PARENT_ID это привязка к родительскому пункту, TITLE тоже понятно что.

Код с выводом:

// Сначала корни и родители, потом дети
$result = SELECT * FROM `menu` ORDER BY `PARENT_ID` IS NULL, `PARENT_ID` ASC, ID ASC;

$menu = [];
$roots = [];
while ($row = mysqli_fetch_assoc($result)) {
  $row['CHILD'] = [];
  // Если не указан родитель PARENT_ID
  // то это корень, добавляем в список корней
  // если указан то это ребенок добавляем его ID к родителю 
  if (empty($parentId = $row['PARENT_ID'])) {
    $roots[] = $row;    
  } else {
    $menu[$parentId]['CHILD'][] = $row['ID'];
  }
  $menu[$row['ID']] = $row;
}

// Рекурсивная функция вывода
function echo_menu($menu, $row) {
  echo '<li>', $row['TITLE'];
  // Если нет детей выводится один <li>TITLE</li>
  // Если дети есть выводятся они рекурсивно:
  // <li>TITLE<ul>...</ul></li>
  if (!empty($row['CHILD'])) {
    echo '  <ul>';
    foreach ($row['CHILD'] as $childId) {
      echo_menu($menu, $menu[$childId]);
    }
    echo '  </ul>';
  }
  echo '</li>';
} 

Потом выводишь меню, начиная с корней:

<li class="menu">
  <?php foreach ($roots as $root_row) echo_menu($menu, $root_row); ?>
</li>

Код не запускал могут быть ошибки.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 6)
Ответ на: комментарий от MOPKOBKA

Это вывод всего меню одним запросом.

Но если хочется вывести только подпункты первого пункта то

SELECT * FROM `menu` WHERE `PARENT_ID` = 1;

Или получить первый пункт и все его подпункты

SELECT * FROM `menu` WHERE `PARENT_ID` = 1 OR `ID` = 1;

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 3)
Ответ на: комментарий от theNamelessOne

Голосую за ltree.

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

Я у себя с помощью ltree храню список видов деятельности (например строительство -> земляные работы -> рытье котлованов), где в категории любого уровня могут быть связанные юрлица.

skyman ★★★★
()