Чуть поигрался, сформировал разметку. Готовое решение, для тех кто хочет сделать небольшое многоуровневое меню. У фела PHP: $tree = [ ['name' => 'Уровень 1', 'id' => 1, 'pid' => 0], ['name' => 'Уровень 1.1', 'id' => 2, 'pid' => 1], ['name' => 'Уровень 1.2', 'id' => 3, 'pid' => 1], ['name' => 'Уровень 1.3', 'id' => 4, 'pid' => 1], ['name' => 'Уровень 2', 'id' => 5, 'pid' => 0], ['name' => 'Уровень 2.1', 'id' => 6, 'pid' => 5], ['name' => 'Уровень 2.2', 'id' => 7, 'pid' => 5], ['name' => 'Уровень 3', 'id' => 8, 'pid' => 0], ['name' => 'Уровень 3.1', 'id' => 9, 'pid' => 8], ['name' => 'Уровень 3.1.1', 'id' => 10, 'pid' => 9], ['name' => 'Уровень 3.1.2', 'id' => 11, 'pid' => 9], ['name' => 'Уровень 1.4', 'id' => 12, 'pid' => 1], ['name' => 'Уровень 2.3', 'id' => 13, 'pid' => 5], ['name' => 'Уровень 3.1.2.1', 'id' => 14, 'pid' => 11], ['name' => 'Уровень 1.4.1', 'id' => 15, 'pid' => 12], ]; function rebuildTree($tree){ foreach ($tree as $key=>$node){ $ref = &$tree[$key]; $branches[$node['id']] = &$ref; $branches[$node['pid']]['chld'][] = &$ref; if ($node['pid'] === 0){ $result[] = &$ref; } } return $result; } echo '<pre>'; print_r(rebuildTree($tree)); echo '</pre>'; Моё PHP: /* * Функция ищет вложенные массивы * Можно использовать в виде */ function child($ch){ echo '<ul>'; foreach($ch as $item){ echo '<li>'. $item['name'] . '</li>'; if(array_key_exists('chld', $item)){ child($item['chld']); } } echo '</ul>'; } //Выводит самые главные категории echo '<ul>'; foreach(rebuildTree($tree) as $category){ echo '<li>' . $category['name'] . '</li>'; child($category['chld']); } echo '</ul>'; --- Добавлено --- Уровень 1 Уровень 1.1 Уровень 1.2 Уровень 1.3 Уровень 1.4 Уровень 1.4.1 Уровень 2 Уровень 2.1 Уровень 2.2 Уровень 2.3 Уровень 3 Уровень 3.1 Уровень 3.1.1 Уровень 3.1.2 Уровень 3.1.2.1
Вот так без рекурсии PHP: <?php $tree = [ ['name' => 'Уровень 1', 'id' => 1, 'pid' => 0], ['name' => 'Уровень 1.1', 'id' => 2, 'pid' => 1], ['name' => 'Уровень 1.2', 'id' => 3, 'pid' => 1], ['name' => 'Уровень 1.3', 'id' => 4, 'pid' => 1], ['name' => 'Уровень 2', 'id' => 5, 'pid' => 0], ['name' => 'Уровень 2.1', 'id' => 6, 'pid' => 5], ['name' => 'Уровень 2.2', 'id' => 7, 'pid' => 5], ['name' => 'Уровень 3', 'id' => 8, 'pid' => 0], ['name' => 'Уровень 3.1', 'id' => 9, 'pid' => 8], ['name' => 'Уровень 3.1.1', 'id' => 10, 'pid' => 9], ['name' => 'Уровень 3.1.2', 'id' => 11, 'pid' => 9], ['name' => 'Уровень 1.4', 'id' => 12, 'pid' => 1], ['name' => 'Уровень 2.3', 'id' => 13, 'pid' => 5], ['name' => 'Уровень 3.1.2.1', 'id' => 14, 'pid' => 11], ['name' => 'Уровень 1.4.1', 'id' => 15, 'pid' => 12], ]; function rebuildTree($tree){ foreach ($tree as $key => $node) { $branches[$node['id']] = $node; } $rootNodes = []; foreach ($tree as $node) { if ($node['pid'] === 0) { $rootNodes[] = &$branches[$node['id']]; } else { $branches[$node['pid']]['chld'][] = &$branches[$node['id']]; } } return $rootNodes; } $constructedTree = rebuildTree($tree); function printTree($tree) { $stack = array(); array_push($stack, array($tree, 0)); while (count($stack) > 0) { list($node, $level) = array_pop($stack); echo str_repeat('----', $level) . $node['name'] . "\n"; if (isset($node['chld'])) { $level++; foreach (array_reverse($node['chld']) as $child) { array_push($stack, array($child, $level)); } } } } foreach($constructedTree as $comment){ printTree($comment); }
Вот ещё варианты функции printTree PHP: function printTree($tree) { $stack = []; $subTree = &$tree; // the considered branch $ind = 0; // we test if we have more elements in the current branch or if we have an upper branch to process while (($into = ($ind < count($subTree))) || count($stack)) { if (!$into) // if all elements of current branch are processed, we restore the upper branch { [$subTree, $ind] = array_pop($stack); } else { // let's print the string, the indentation is calculated by the stack level echo str_repeat(' ', (count($stack) + 1) * 2), $subTree[$ind]['name'], PHP_EOL; // if there's a child branch we save the current processing branch and position // and we prepare to process the sub-branch if ($subTree[$ind]['chld'] ?? false) { $stack[] = [&$subTree, $ind]; $subTree = &$subTree[$ind]['chld']; $ind = -1; // will become 0 in the next instruction ~ if you don't like it use: $ind = 0; continue; } } $ind++; } } PHP: function printTree($tree) { $stack = []; foreach ($tree as $node) { if (empty($node['pid'])) { $stack[] = [$node, 0]; } } // add this line: $stack = array_reverse($stack); while (!empty($stack)) { list($node, $depth) = array_pop($stack); echo str_repeat(' ', $depth) . $node['name'] . PHP_EOL; if (isset($node['chld'])) { foreach (array_reverse($node['chld']) as $child) { $stack[] = [$child, $depth + 1]; } } } }