Не могу создать массив с нужной структурой: нужно чтобы создавало простую структуру, не зависимо от глубины функции, например: $display[1]['name'] = Категория 1; $display[2]['name'] = Категория 1.1; $display[3]['name'] = Категория 1.1.1; $display[4]['name'] = Категория 2; function PriceTree($catid) { // построение дерева прайса $sql = "SELECT * FROM ".TABLE_PCATEGORIES." WHERE parent_id = '$catid'"; // вывод категорий прайса $result = mysql_query($sql); while ($row = mysql_fetch_array($result)) { $i++; $cid = $row['pcategories_id']; $cname = $row['pcategories_name']; $display[$i]['name'] = $cname; $display[$i]=PriceTree($cid); } return $display; } PriceTree(0);
Сразу предупреждаю - по голове не бить. Это хоть и первое, что пришло, но все таки в голову ))) PHP: <?php function getPriceTree($id_cat = 0) { $sql = sprintf("SELECT * FROM %s WHERE parent_id = %d", $table_name, $id_cat); $result = mysql_query($sql); while($row = mysql_fetch_assoc($result)){ $display[]['name'] = $row['name']; getPriceTree($row['id']); } return $display; } ?> И еще... Не знаю, будут ли проблемы с областью видимости $display. Если не получится - извини, сам только недавно знаком с PHP
ой не... жуть какая. во-первых, запрос на каждом уровне, а во-вторых, отсутствие сортировки (которая аукнется, если добавится редактирование этого списка и реальный порядок не будет совпадать с порядком PRIMARY), в-третьих, в функцию в таких деревьях нужно передавать параметры по ссылке. лучше эту реализацию не использовать
могу дать свою. но она под другую базу со своей спецификой, но допилить можно при желании. что-то очень старое.... помню, что в $tail остаются неиспользованные детали, а в $tree - само дерево. отдрачивалось на скорость выполнения PHP: <?php $res = mysql_query("SELECT * FROM `blogs` ORDER BY `id`;"); $tail = array(); while($data = mysql_fetch_assoc($res)) array_push($tail,$data); function f_Tree_Blog_Fast (&$tail) { $arr_pare = array(); foreach ($tail as $key=>$item) $arr_pare[$key]=$item['mother_blog_id']; asort($arr_pare); $tree = array(); foreach($arr_pare as $key=>$item) if($item == null) { array_push($tree,$tail[$key]); unset($arr_pare[$key]); unset($tail[$key]); } else break; foreach($tree as $key=>$item) f_BuildLayer($arr_pare,$tail,$tree[$key]); return $tree; } function f_BuildLayer(&$arr_pare,&$tail,&$base) { $base['next'] = array(); $i = 0; while($pos = array_search($base['id'],$arr_pare)) { array_push($base['next'],$tail[$pos]); unset($arr_pare[$pos]); if($tail[$pos]['is_group']=='y') { f_BuildLayer($arr_pare,$tail,$base['next'][$i]); unset($tail[$pos]); } $i++; } if(count($base['next'])==0) unset($base['next']); } $tree = f_Tree_Blog_Fast($tail); ?>
по идее должно вывести что-то типа Категория1 Категория1.1 Категория1.2 Категория2 и т.д. А PRIMARY же задает только уникальный идентификатор и как бы на результат вывода не сильно влияет. Или я не прав
если я поменяю местами категория 1.1 и 1.2? хотя... один фиг. в моей тоже поменяется... для таких целей нужен usort по какому-то параметру типа weight
Можно же потом отсортировать готовый массив и как раз получиться то что надо, даже связь с ключами сохранять не надо
Согласен. Но вопрос был только создать массив определенной структуры, а дальше уже работать только с этим массивом
Доброго времени суток. Сразу предупрежу, что не очень хорошо разбираюсь в PHP,MySQL. Столкнулся с необходимостью изменить редактор каталога, добавив функцию удаления "папки" со всем ее содержимым. Данные хранятся в таблице myGroups (отстальное содержимое пока меня не интересует) Логика подсказывает, что необходимо написать рекурсивную функцию, а посты выше, что делать в этой функции 400+ запросов - неверный шаг. Вариант, предложенный Volt`ом уж очень непонятен и сложен для понимания =( В темных глубинах сознания родился вариант с буфером. Грузим все "папки" из myGroups в массив-буфер одним запросом, а потом уже выбираем тех наследников, которых нам надо удалить и делаем соответствующие запросы. Будет ли данный вариант оптимален?
не супероптимально, но верно. учитывайте, что вы можете упереться в быстродействие (грубый код на 100 узлов выполнялся аж 0,4с!). посмотрите мой код выше, может это вас натолкнёт на какие-то соображения
Код не понял. Тяжело разбираться, когда комментариев нет =( За подсказку с оптимальностью спс. 0.4с переживу ))
PHP: <?php //запрос в базу. получаем все записи, которые могут быть использованы в дереве блогов $res = mysql_query("SELECT * FROM `blogs` ORDER BY `id`;"); //собираем их в массив, для того чтобы потом этот массив скормить построителю дерева $tail = array(); while($data = mysql_fetch_assoc($res)) array_push($tail,$data); function f_Tree_Blog_Fast (&$tail) //построитель { $arr_pare = array(); //создается легкий массив для быстрого индекса записей большого массива foreach ($tail as $key=>$item) $arr_pare[$key]=$item['mother_blog_id']; asort($arr_pare); //строим первый слой дерева. для этого ищутся блоги, у которых 'mother_blog_id'==null. //делается это для скорости на индексном массиве $tree = array(); foreach($arr_pare as $key=>$item) if($item == null) { array_push($tree,$tail[$key]); //нашли хоть и в индексном массиве, но в дереве подцепляем уже большую запись unset($arr_pare[$key]); //удаляем из индекса unset($tail[$key]); //удаляем из входного массива } else break; // после asort все null находились вверху. если встретилась нормальная запись, значит первый слой сделан //каждая запись может стать основанием новой ветки дерева. построим. foreach($tree as $key=>$item) f_BuildLayer($arr_pare,$tail,$tree[$key]); return $tree; } function f_BuildLayer(&$arr_pare,&$tail,&$base) //&индекс-массив, &остатки входного массива, &основа для строительства ветки { $base['next'] = array(); //ветку будем достраивать сразу в элементе $i = 0; while($pos = array_search($base['id'],$arr_pare)) { array_push($base['next'],$tail[$pos]); unset($arr_pare[$pos]); //база спроектирована так, что элемент знает: конечный он или не конечный //проверку на группу можно запросто убрать. всё должно работать if($tail[$pos]['is_group']=='y') { f_BuildLayer($arr_pare,$tail,$base['next'][$i]); unset($tail[$pos]); } $i++; } //если ветка не выросла, то закрываем её if(count($base['next'])==0) unset($base['next']); } //скармливаем массив построителю $tree = f_Tree_Blog_Fast($tail); ?>
Пытался написать функцию удаления "папки" из каталога со всм содржимым, но так ничего не получилось. Подскажите, пожалуйста, где может быть ошибка? Как заставить код функционировать? Таблица mysql, содержащая каталоги: --------------------------------- ID (int) - уникальный идентификатор PID (int) - иднтификатор родителя data (text) - прочая информация Переменные: ---------------------------------- $ecmode - тип операции (в данном случае удаление) $_SITE['DB_PREFIX'] - некоторый префикс бд (s_) $ecdir - id папки, которую удаляем $ecbuffer = array (); - буфер со значениями каталогов $ecdbuffer[] = array(); - буфер, удаляемых элементов, который в конечном счете чистится PHP: <?php # DELETE FOLDER: if ($ecmode==5) { $sql = "SELECT id, pid FROM ".$_SITE['DB_PREFIX']."gCatalogGroups ORDER BY id"; $ecfbuffer_sz =0; if ($rowq=mysql_query($sql)) { # создаем буфер вида: $ecbuffer[<id>] = <pid> while ($row = mysql_fetch_object($rowq)) { $ecfbuffer[$row->id] = $row->pid; $ecfbuffer_sz++; } mysql_free_result($rowq); # ищем ключик в буфере if (array_key_exists($ecdir, $ecfbuffer)){ @oops('dir exists'); ecdirdrop($ecdir, $ecfbuffer); @oops('set parent'); for ($i=0; $i<count($ecdbuffer); $i++) { # удаляем "файлы" $sql="DELETE FROM ".$_SITE['DB_PREFIX']."gCatalogGoodies WHERE pid='".$ecdbuffer[$i]."'"; mysql_query($sql); # удаляем "папки" $sql="DELETE FROM ".$_SITE['DB_PREFIX']."gCatalogGroups WHERE pid='".$ecdbuffer[$i]."'"; mysql_query($sql); } $ecdir = $ecfbuffer[$ecdir]; } else { @oops('Del: target folder does not exists.'); $ecdir = 0; } } else { @oops('Del: buffer is empty'); } } ?> Функция ecdirdrop(): PHP: <?php function ecdirdrop($fid, $fbuf){ # Пока есть наследник FindFirstChild мы ищем конец while(($ecdd=array_search($fid,$fbuf))&&($ecdd!==NULL)){ if ($ecdd!=NULL) ecdirdrop($ecdd,$fbuf); oops(array_search($fid,$fbuf)); } #while # Когда конечный каталог найден и у него нет наследника, мы его чистим от файлов и удаляем $ecdbuffer[] = $fid; # При этому станавливаем его ключ в буфере в минус, чтобы не находить $fbuf[$fid]=1000000; @oops('Удалена папка'); } ?> В итоге страница виснет и удаление не происходит.