цикл через многоуровневый массив с неизвестным количеством уровней

У меня есть таблица категорий, которая выглядит так:

----------------------------------------
|  id   |  parentId  |  Name           |
----------------------------------------
   1          0         Cat 1
   2          0         Cat 2
   3          0         Cat 3
   4          2         Cat 4
   5          3         Cat 5
   6          5         Cat 6

В основном мне нужно перебирать категории, создавая html-список UL LI, как показано ниже:

<ul id="categories">
    <li id="1">Cat 1</li>
    <li id="2">Cat 2
       <ul>
           <li id="4">Cat 4</li>
       </ul>
    </li>
    <li id="3">Cat 3
        <ul>
           <li id="5">Cat 5
               <ul>
                   <li id="6">Cat 6</li>
               </ul>
           </li>
        </ul>
    </li>
</ul>

У меня серьезные проблемы с попыткой повторить это, пытаясь создать вышеуказанный html. Идентификатор может быть любым количеством уровней внутри parentId. Я делаю это в PHP. Поскольку существует n-е количество уровней в глубину, я думаю, мне нужно выполнить какую-то функцию array_walk, но не искать, как это сделать. Кроме того, чтобы немного усложнить ситуацию, машина, на которой она работает, работает на PHP4, и я знаю, что она нуждается в обновлении, но она не может работать как минимум, поэтому в идеале мне нужно решение на php 4. Как мне это сделать?


person azzy81    schedule 21.02.2012    source источник
comment
Таблица получена из SQL-запроса?   -  person Eugen Rieck    schedule 21.02.2012
comment
да, он начинается с таблицы mysql, которая помещается в класс/объект категорий, однако, если я могу сделать это в конце SQL, тогда отлично   -  person azzy81    schedule 21.02.2012
comment
возможный дубликат: stackoverflow.com/questions/8847365/ и stackoverflow.com/questions/7649803/   -  person Yoshi    schedule 21.02.2012


Ответы (3)


Попробуйте метод левого/правого дерева для хранения иерархической информации в базе данных.

http://blogs.sitepoint.com/hierarchical-data-database/

Это то, что я делаю на своем веб-сайте, где у меня есть многоуровневые LI, которые должны открываться в формате 1: 6 и иметь дочерние элементы 2: 3, 4: 5, где первое число — «левое», а второе — «правое». '. На данный момент у меня около 5 уровней, но у вас может быть намного больше. Это просто вопрос разработки интерфейса для установки правильных значений левого/правого в зависимости от позиции, в которую вы их добавляете.

Вам просто нужно добавить в таблицу столбцы «lft» и «rgt» (как описано в этой статье).

введите здесь описание изображения

person Benno    schedule 21.02.2012
comment
Я читаю сейчас m8 спасибо. Я дам вам знать, как я буду ^^ - person azzy81; 21.02.2012
comment
* Извините, только что понял, что в этом сообщении в блоге есть два метода. На первой странице есть модель смежности (это то, что вы сейчас пытаетесь, я думаю). Вторая/третья страницы - это метод левого/правого дерева, который немного сложнее, но, по моему опыту, гораздо более расширяемый. - person Benno; 21.02.2012
comment
Мне очень нравится это решение для вложенных наборов, и я никогда о нем не слышал. На самом деле я не использовал его в качестве своего решения в конце концов, однако я считаю, что из всех решений это самый приятный и самый расширяемый способ, поэтому я отмечаю это как мой принятый ответ. Спасибо всем, кто ответил... все ваши легенды ^^ - person azzy81; 22.02.2012
comment
Просто для людей, интересующихся тем, как я достиг своего решения, мне удалось снова включить свою возражающую ориентированную голову и выяснить, что я могу вытащить все дочерние категории при загрузке любой категории. Теперь у моего объекта есть дочерний массив, и если родительский идентификатор равен 0, я знаю, что у него есть родитель, поэтому я возвращаю объект обратно. Как только я исправил свой объект, это была очень простая функция для переноса тегов ul/li в нужных местах. - person azzy81; 22.02.2012

Сначала создайте древовидную структуру и вставьте свои категории в дерево, используя id и parent_id. Затем попробуйте Depth-first_search, используя либо список ссылок на обрабатываемые массивы, либо рекурсию.

function printRecList($tree){
   // exit condition
   if (is_string($tree))
       echo "<li>$tree</li>";

   echo "<ul>";
   foreach ($tree as $subtree)
       printRecList($subtree); // recursion step
   echo "</ul>";
}
person Basti    schedule 21.02.2012

Ваша база данных структурирована так, что вы не можете сделать это с помощью одного запроса mysql, и вы должны делать это рекурсивно. Что-то в соответствии с:

function print_children ($id) {
    $children = query("SELECT * FROM `table` WHERE `parentId` = " . (int)$id);
    if (!empty($children)) {
         echo '<ul>';
         foreach ($children as $child) {
              echo '<li>' . $child['name'];
              print_children($child['id']);
              echo '</li>';
         }     
         echo '</ul>';
    }
}

print_children(0);

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

person gintas    schedule 21.02.2012