Знаю что эта тема замусолена в просторах рунета и не только, но за 30 часов решения так и не нашел. Переспрашивал и перегуглил всех кого мог, обычно используют функции mysql для этого,что тоже не для меня. Вариант с each тоже отпадает, так как с php 7.2 он больше не рабочий. А мне проект поддерживать еще не 1 год. Вот сама задача. Должна быть навигация с вложенностью N раз. имеется массив $categories с полями last_id,id, итд для примера PHP: $array = array(); $array[] = array('id'=>8, 'pid'=>4, 'header'=>'H'); $array[] = array('id'=>1, 'pid'=>0, 'header'=>'A'); $array[] = array('id'=>11, 'pid'=>10, 'header'=>'M'); $array[] = array('id'=>10, 'pid'=>5, 'header'=>'L'); $array[] = array('id'=>9, 'pid'=>5, 'header'=>'K'); $array[] = array('id'=>4, 'pid'=>0, 'header'=>'D'); $array[] = array('id'=>12, 'pid'=>9, 'header'=>'N'); $array[] = array('id'=>5, 'pid'=>1, 'header'=>'E'); $array[] = array('id'=>7, 'pid'=>3, 'header'=>'G'); $array[] = array('id'=>3, 'pid'=>0, 'header'=>'C'); $array[] = array('id'=>2, 'pid'=>0, 'header'=>'B'); $array[] = array('id'=>6, 'pid'=>1, 'header'=>'F'); нужно его собрать, и вывести. Что я делал. PHP: function getTree($categories, $depth = '0') { $array = array(); foreach ($categories as $cat) { if ($cat['pid'] == $depth) { $cats[]=CategoriesModel::getTree($categories, $cat['id']); $array[] = array_merge($array, $cats); } } return $array; } Вроде бы все и отлично, но когда делаю var_dump или через цикл пропускаю результат. Имеем пустоту. Спойлер: Очень длинный список с пустотой. HTML: Array ( [0] => Array ( [0] => Array ( [0] => Array ( [0] => Array ( [0] => Array ( [0] => Array ( ) ) [1] => Array ( [0] => Array ( [0] => Array ( ) ) [1] => Array ( ) [2] => Array ( ) ) [2] => Array ( [0] => Array ( [0] => Array ( ) ) [1] => Array ( [0] => Array ( [0] => Array ( ) ) [1] => Array ( ) [2] => Array ( ) ) [2] => Array ( ) [3] => Array ( ) [4] => Array ( ) ) [3] => Array ( [0] => Array ( [0] => Array ( ) ) итд ( В отчаянии прошу вашей помощи, наставлением, и примерами для такой задачи если вы их реализовывали. Желательно современные решения)
Я для этих целей использовал одну таблицу в бд с такой структурой: Код (Text): CREATE TABLE `category` ( `id` int(11) NOT NULL, `parent_category` int(11) DEFAULT NULL, `name` varchar(200) NOT NULL, `description` varchar(1000) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Dumping data for table `category` -- INSERT INTO `category` (`id`, `parent_category`, `name`, `description`) VALUES (1, NULL, 'Посуда', 'Декоративная посуда, тарелки и все такое'), (2, 1, 'Тарелки', 'Тарелки круглые квадратные'), (3, 1, 'Рюмки', 'Рюмки всех видов'), (4, NULL, 'Электроника', 'Сотовые телефоны, умные часы а так остальная электроника'), (5, 2, 'Блюдницы', 'Тарелки для блюд и сервировки стола'); -- -- Indexes for dumped tables -- -- -- Indexes for table `category` -- ALTER TABLE `category` ADD PRIMARY KEY (`id`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `category` -- ALTER TABLE `category` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6; Теперь выборка: PHP: //демонстрация echo "<br>"; foreach ($categoryes as $val) { if (is_null($val['parent_id'])) { echo $val['name'] . "<br>"; foreach ($categoryes as $val1) { if ($val['id'] == $val1['parent_id']) { echo "--" . $val1['name'] . "<br>"; } } } } И все, получаем свое меню. Важно: код будет работать только с PHP-версией выше 7 --- Добавлено --- Допустима любая вложеность.
Отлично, мне нравится способ, вроде и без рекурсии. Конечно при тесте 3 уровень вложенности не работал, и должен ли работать. Ладно сейчас еще протестирую, базу чуть иначе сделаю. А так рад буду и другим примерам.
@xaker01, третий тоже работал вроде. Вообще, я думаю о рекурсии. Мне не нравится что столько циклов требуется если увеличивать вложенность.
а так вот в чем дело) для 3 вложенности нужен новый цикл), я думал нашел вариант без него) тут без рекурсии не обойтись ни как., так что я в эту сторону тоже копаю. У меня потом задача еще веселе, сортировка выводить 1 категорию, или 2 , и также субкатегорию, и суб -суб.... категорию.
PHP: function test($categoryes, $category_id = NULL) { foreach ($categoryes as $category) { if (is_null($category['parent_id']) && is_null($category_id)) { echo "<ul><li>" . $category['name'] . '</li>'; test($categoryes, $category['id']); } else if ($category['parent_id'] == $category_id) { echo "<ul><li>" . $category['name'] . '</li>'; test($categoryes, $category['id']); } } echo "</ul>"; } остается стилизовать. Но я бы всеравно использовал циклы если не нужны вложенности более трех.)) --- Добавлено --- PHP: //использование test($categories);
PHP: function getTree($categories, $pid = 0){ $tree = []; foreach($categories as $k=>$v){ if($v['pid'] == $pid){ unset($categories[$k]); $tree[] = [ 'id' => $v['id'], 'pid' => $v['pid'], 'header' => $v['header'], 'childs' => getTree($categories, $v['id']), ]; } } return $tree; } echo '<pre>'; print_r(getTree($array)); echo '</pre>'; --- Добавлено --- а вот таже самая рекурсия но для постройки li списка Код (Text): function buildLiTree($categories, $pid = 0){ $string = '<ul>'; foreach($categories as $k=>$v){ if($v['pid'] == $pid){ unset($categories[$k]); $string .= '<li>'; $string .= '<a href=' . $v['id'] . '>' . $v['header'] . '</a>'; $tmp = buildLiTree($categories, $v['id']); $string .= strpos($tmp, 'li') ? $tmp : ''; $string .= '</li>'; } } $string .= '</ul>'; return $string; } echo buildLiTree($array);
я тоже через pid, другие способы , скажем не очень. Кстати твой способ полностью сработал) Прям точь в точь как надо.. Осталось только все это в библеотеку хорошую оформить и все)