Есть такой массив: Код (Text): Array ( [0] => Array ( [0] => Главный каталог 1 [1] => Каталог второго уровня 1 главного каталога 1 [2] => Спорт ) [1] => Array ( [0] => Главный каталог 1 [1] => Каталог второго уровня 2 главного каталога 1 [2] => Путешествия ) [2] => Array ( [0] => Главный каталог 1 [1] => Каталог второго уровня 2 главного каталога 1 [2] => Погода ) [3] => Array ( [0] => Главный каталог 2 [1] => Каталог второго уровня 1 главного каталога 2 [2] => Часы ) [4] => Array ( [0] => Главный каталог 2 [1] => Каталог второго уровня 1 главного каталога 2 [2] => Монеты ) ) Задача собрать меню вида Код (Text): Главный каталог 1 Каталог второго уровня 1 главного каталога 1 Спорт Каталог второго уровня 2 главного каталога 1 Путешествия Погода Главный каталог 2 Каталог второго уровня 1 главного каталога 2 Часы Монеты Подскажите куда копать?
массив говно. Добавлено спустя 54 секунды: надо пересобрать, если можно. из такого массива ничего путного не выйдет.
Да не, чего сразу говно? Нормальный такой массив. Только не понятно: названия каталогов есть, а ссылки где хранятся?
В базе каталоги хранятся в виде: Главный каталог 1/Каталог второго уровня 1 главного каталога 1/Спорт/ Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Путешествия/ Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Погода/ Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Часы/ Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Монеты/ как из этих исходных данных лучше сформировать меню? Может быть надо изменить алгоритм парсинга каталогов в базу как таковых? Например сделать отдельную таблицу где бы хранился каждый каталог с id родителя?
первый массив - говно. потому что там всё не так =) как именно они хранятся в базе? вот прям такими строками? скажи точнее в любом случае это не сложно. доберусь до компа - подскажу. пока дай больше инфо.
Прямо так, строками разделёнными обратным слешем, но у меня был вариант это переделать к виду: "сделать отдельную таблицу где бы хранился каждый каталог с id родителя" Первый массив собрал функцией explode() какраз из этих строк, была идея упорядочить выборку каталогов, потом сформировать этот массив. После пройтись по нему в цикле отбирая по принципу: записываем элемент с индексом 0, записываем элемент с индектом 1, записываем элемент с индексом 2. (и получаем первое дерево меню) В следующей интерации проверяем изменения элементов 0 и 1 и если их нет добавляем в первое дерево ещё один пункт в каталог второго уровня. Если изменения есть соответственно или создаём новое дерево или добавляем каталог второго уровня к существующему. Но в такой ситуации плохо понимаю как работать с разными по уровню вложенности каталогами...
не, это разу надо делать. их всегда так: один каталог, один подкаталог, и раздел? Всегда три элемента? всегда два слеша?
Нет по разному, от одного до 5ти. Слэш ещё в конце есть, но я его выпиливал перед формированием массива за ненадобностью.
Нужно, чтобы папки (раделы) были как-то представлены, чтобы у них был свой id в БД. Тогда можно строить иерархию. А просто вывести в виде деревца, так я сделал, но нужно ли? Как ссылки делать, по каким id ориентироваться? Или тут id - это порядковый номер записи?
Код (PHP): $instr= 'Главный каталог 1/Каталог второго уровня 1 главного каталога 1/Спорт/ Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Путешествия/ Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Погода/ Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Часы/ Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Монеты/'; $tArr=explode("\n", $instr); $menu=array();//тут иерархия $counter=0;//можно с 1 начать, если в базе id начинается с 1 foreach($tArr as $line){ $line=trim($line,'/');//по краям убираем слеш $tempArr=explode('/', $line);//временный массив из строки $key1=array_shift($tempArr);//ключ для 1 уровня $key2=array_shift($tempArr);//ключ для 2 уровня $key3=array_shift($tempArr);//ключ для 3 уровня if(!isset($menu[$key1])){ $menu[$key1]=array(); } if(!isset($menu[$key1][$key2])){ $menu[$key1][$key2]=array(); } if(!isset($menu[$key1][$key2][$key3])){ $menu[$key1][$key2][$key3]=array(); } $menu[$key1][$key2][$key3]=$counter; $counter+=1; } //echo '<pre>'; //print_r($menu); //echo '</pre>'; //выводим меню function tree(&$arr,$lvl=0){ $lvl++; if(is_array($arr)){ echo "\n",str_repeat("\t",$lvl),'<ul>',"\n"; foreach($arr as $key=>$branch){ $isArray=is_array($branch); if(!$isArray){ echo str_repeat("\t",$lvl),'<li><a href="?id='.$branch.'">',$key; }else{ echo str_repeat("\t",$lvl),'<li>',$key; } tree($branch,$lvl); if(!$isArray){ echo '</a></li>',"\n"; }else{ echo '</li>',"\n"; } } echo str_repeat("\t",$lvl),'</ul>',"\n"; } $lvl--; } tree($menu); Добавлено спустя 1 минуту 5 секунд: Но всё это не правильно, т.к. теперь в тексте нельзя хранить слэш, чтобы не нарушить структуру.
Уже тут увидел, можно оптимизировать внутри функции, меньше проверок делать. Во, так покрасивей Код (PHP): $instr= 'Главный каталог 1/Каталог второго уровня 1 главного каталога 1/Спорт/ Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Путешествия/ Главный каталог 1/Каталог второго уровня 2 главного каталога 1/Погода/ Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Часы/ Главный каталог 2/Каталог второго уровня 1 главного каталога 2/Монеты/'; $tArr=explode("\n", $instr); $menu=array();//тут иерархия $counter=0;//можно с 1 начать, если в базе id начинается с 1 foreach($tArr as $line){ $line=trim($line,'/');//по краям убираем слеш $tempArr=explode('/', $line);//временный массив из строки $key1=array_shift($tempArr);//ключ для 1 уровня $key2=array_shift($tempArr);//ключ для 2 уровня $key3=array_shift($tempArr);//ключ для 3 уровня if(!isset($menu[$key1])){ $menu[$key1]=array(); } if(!isset($menu[$key1][$key2])){ $menu[$key1][$key2]=array(); } if(!isset($menu[$key1][$key2][$key3])){ $menu[$key1][$key2][$key3]=array(); } $menu[$key1][$key2][$key3]=$counter; $counter+=1; } //выводим меню function tree(&$arr,$lvl=0){ $lvl++; if(is_array($arr)){ echo "\n",str_repeat("\t",$lvl-1),'<ul>',"\n"; foreach($arr as $key=>$branch){ $isArray=is_array($branch); if($isArray){ echo str_repeat("\t",$lvl),'<li>',$key; tree($branch,$lvl); echo str_repeat("\t",$lvl),'</li>',"\n"; }else{ echo sprintf('%s<li>[url="?id=%d"]%s[/url]</li>%s',str_repeat("\t",$lvl),$branch,$key,"\n"); } } echo str_repeat("\t",$lvl-1),'</ul>',"\n"; } $lvl--; } tree($menu);
хочу рекурсию. оказалось что построить дерево каталогов и списка каталогов нетривиальная задача. никогда бы не подумал...
Спасибо за ответы! Вообще ID в базе есть. Вот что есть: id - Собственно уникальный идентификатор записи. Генерятся автоматически когда добавляется новый каталог. Новый каталог добавляется при импорте прайс листа, если парсер разбирая csv файл не нашёл совпадений в базе. Точнее так, каталог создаётся и его id помещается в соответсвующее поле таблицы с товарами. Если же парсер нашё совпадение, то он берёт ID совпавшего поля и проделывает уже с ним описанное ранее. price - К какому прайс листу принадрежит запись. Так как записи выгружаются из разных прайс листов соответственно существует база с их перечнем идентификатором, заголовком описанием и прочими вещами. Это по сути линк на соответствующее поле в той таблице. catalogs - Вот тут и хранится текст вида "Главный каталог 1/Каталог второго уровня 1 главного каталога 1/Спорт/". Текст состоит только из пробелов и символов литиницы и кириллицы, разбитых обратными слешами по уровню вложенности, никаких спецсимволов тут быть не может. time - время создания/изменения записи
Дай угодаю, ты наверно был с похмелья? По себе заметил, что с похмелья рекурсивный обход всяких там parent_id даётся трудновато... В последний раз совсем недавно сталкивался с этим, утром еле встал после вечерней попойки, наверно часа 4 никак не мог сообразить как это делается (через 4 часа, видимо наступило отрезвление) )) По теме - нужно, конечно, вникать в конкретную задачу, как там всё работает, но на первый взгляд мне кажется, что структура б.д. должна быть несколько другой. Думаю, для каталогов должна быть отдельная таблица...