Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Рекурсивная функция [2]
Форумы портала PHP.SU » » Хранение данных, их вывод и обработка » Рекурсивная функция

Страниц (4): « 1 [2] 3 4 »
 

16. egir - 25 Августа, 2011 - 00:17:46 - перейти к сообщению
DeepVarvar пишет:
Так мой пример разбирает весь массив из одного запроса по вложеностям и ничего не нужно будет при добавлении нового пункта переформировывать.
Зачем крутить лишние циклы и запросы?


Не понял что Вы хотели сказать. У человека стоит задача сначала сформировать массив от потомка до родителя, а потом с него уже что-то формировать. Судя по его примеру у него нет таблицы дерева связей, он работает напрямую с таблицей "категорий" - как он их называет. Как вы одним запросом в его случае достаните всех родителей в таблице вида:

id | pid | name | idObject
1 | 0 | Категория 1 | 111
...
3 | 1 | Категория 1.1 | 222
...
10 |3 | Категория 1.1.1 | 333
...
45 | 10 | Категория 1.1.1.1 | 444

?
17. DeepVarvar - 25 Августа, 2011 - 00:20:13 - перейти к сообщению
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT id,pid,name,idObject FROM tbl
18. egir - 25 Августа, 2011 - 10:02:39 - перейти к сообщению
DeepVarvar пишет:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT id,pid,name,idObject FROM tbl


А если в таблице 100 000 записей, будете их все в цикле пробегать, пока не соберете массив? Или будете искать в массиве с 100 000 элементов? Как по мне, лучше 20 запросов в БД.
19. Kubert - 25 Августа, 2011 - 10:03:55 - перейти к сообщению
egir

Вот так достану:
CODE (htmlphp):
скопировать код в буфер обмена
  1.  
  2. $result=mysql_query("SELECT id,pid,name,idObject FROM category ORDER BY sort,id");
  3. if(mysql_num_rows($result)>0){
  4.         $cats = array();
  5.         $fintParent = array();
  6.         while($cat =  mysql_fetch_assoc($result)){
  7.                 $cats[$cat['pid']][] =  $cat;
  8.                 $listCat[$cat['id']]['id'] =  $cat['id'];
  9.                 $listCat[$cat['id']]['pid'] =  $cat['pid'];
  10.                 $listCat[$cat['id']]['idObject'] =  $cat['idObject'];
  11.                 $listCat[$cat['id']]['name'] =  $cat['name'];
  12.         }
  13. }
  14.  


И выведу:
CODE (htmlphp):
скопировать код в буфер обмена
  1.  
  2. function listTree($cats,$parent_id){
  3.         if(is_array($cats) and isset($cats[$parent_id])){
  4.                 $tree = '<ul>';
  5.                         foreach($cats[$parent_id] as $cat){
  6.                                 $tree .= '<li>'.$cat['name'];
  7.                                 $tree .= listTree($cats,$cat['id']);
  8.                                 $tree .= '</li>';
  9.                         }
  10.                 $tree.= '</ul>';
  11.         }
  12.         else return null;
  13.         return $tree;
  14. }
  15.  
  16. //echo listTree($cats,0);
  17.  



DeepVarvar
Функция эта у меня есть(выше написал)! Но спасибо, Вам!
Но затея как раз и состояла в том чтобы в ссылке link прописывать полный путь потомков.
типа:
href="/?idObject1=111&idObject2=222&idObject3=333&idObject4=444"
где 444 активный пункт меню.

+ это поможет мне составить "строку навигации".

А может быть вообще гоню и такие вложенности делают по другому?! Однако


egir
Добавлю WHERE так как у меня в одной таблице категорий лежат все категории для 300 сайтов. а в каждом сайте примерно от 5 до 50 пунктов.
Но я уже подумывал делать сохранять полный путь всех потомков в БД...
Вот теперь и незнаю что делать)

Но если я буду прописывать в БД полный путь потомков, типа "111,222,333,444",
мне все равно придется при добавлении или обновлении страницы, необходимо будет запускать эту злосчастную функцию Ха-ха

А касательно большого кол-во запросов. Уж не хотелось бы этого делать, так как для этого все и замутилось. В данный момент на сайтах стоят как раз такие "обработчики" которые в цикле обращаются постоянно к БД.

Парни помогите, я уже замучился!
20. EuGen - 25 Августа, 2011 - 10:48:31 - перейти к сообщению
Надеюсь, это поможет
PHP:
скопировать код в буфер обмена
  1. $rgTest=array(
  2. array('id'=>3, 'parent_id'=>5),
  3. array('id'=>1, 'parent_id'=>0),
  4. array('id'=>7, 'parent_id'=>3),
  5. array('id'=>5, 'parent_id'=>0),
  6. array('id'=>6, 'parent_id'=>3),
  7. array('id'=>4, 'parent_id'=>3),
  8. array('id'=>2, 'parent_id'=>7),
  9. array('id'=>8, 'parent_id'=>5),
  10. array('id'=>9, 'parent_id'=>4)
  11. );
  12. function getNodesByParent(&$rgData, $parent_id, $bReturnIdOnly=false)
  13. {
  14.    $rgResult=array();
  15.    foreach($rgData as $rgRow)
  16.    {
  17.       if($rgRow['parent_id']==$parent_id)
  18.       {
  19.          $rgResult[]=$bReturnIdOnly?$rgRow['id']:$rgRow;
  20.       }
  21.    }
  22.    return $rgResult;
  23. }
  24.  
  25. function getTree(&$rgData, $id=0)
  26. {
  27.    $rgResult=array();
  28.    foreach(getNodesByParent($rgData, $id) as $rgChildNode)
  29.    {
  30.       $rgResult[$rgChildNode['id']]=getTree($rgData, $rgChildNode['id']);
  31.    }
  32.    return $rgResult;
  33. }
  34. $rgResult=getTree($rgTest);
  35. print_r($rgResult);
21. egir - 25 Августа, 2011 - 10:54:55 - перейти к сообщению
Я раньше писал этот пример Kubert Вы пробывали? Он как раз возвращает массив, которой вроде Вам нужен. А если не хотите запросы, то нужно делать таблицу связей и формировать связи только при добавлении новой категории или что там у Вас. Я у себя так делаю, связи формируются достаточно быстро и один раз, а потом одним запросом (правда сложным), достается все что нужно.

PHP:
скопировать код в буфер обмена
  1.  
  2. function find($id, $listId = array())
  3. {
  4.               //Запрос к БД, чтобы достать инфу о текущей категории
  5.         $res = mysql_query("SELECT * FROM `table` WHERE (`id` = ".$id.")");
  6.         $row = mysql_fetch_array($res);
  7.  
  8.         //Помещаем ID категории в массив
  9.         $listId[] = (int)$row["id"];
  10.  
  11.         //Проверяем существует ли у данной категории родитель
  12.         if((int)$row["pid"] === 0)
  13.         {
  14.                 //Переворачиваем массив, чтобы в начале был родитель, а за ним дети [это уже по желанию]
  15.                 $listId = array_reverse($listId);
  16.                 //Возвращаем массив
  17.                 return $listId;
  18.         }
  19.         else
  20.         {
  21.                 //Ищем родителя данной категории
  22.                 find($row["pid"], $listId);
  23.         }
  24. }
  25.  
  26. //Передаем ID категории, родите которой нужно найти
  27. print_r(find(45));
  28.  
  29.  
22. Kubert - 25 Августа, 2011 - 11:09:47 - перейти к сообщению
egir
м-м-м... у меня не работает... пытаюсь чтото менять всеравно не работает...
23. egir - 25 Августа, 2011 - 11:10:57 - перейти к сообщению
Kubert пишет:
egir
м-м-м... у меня не работает... пытаюсь чтото менять всеравно не работает...

а какая ошибка?
24. Kubert - 25 Августа, 2011 - 11:15:23 - перейти к сообщению
egir
В том то и дело никакой! просто пустой экран
(Добавление)
EuGen
буду разбираться, пробывать! Спасибо!
25. EuGen - 25 Августа, 2011 - 11:17:25 - перейти к сообщению
Kubert
Выбирайте данные одним запросом в формате массива id - parent_id
Превратить его в древовидный можно потом (как - я описал в своем предыдущем комментарии).
С древовидной структурой затем можно уже будет делать что требуется. Вдобавок, это не потребует огромного количества запросов.
26. Kubert - 25 Августа, 2011 - 11:20:01 - перейти к сообщению
egir
И всеже если есть у нас уже имеется массив всех "категорий" с одним id потомком, то можно обойтись без запросов к БД. Это рациональнее. Так как к примеру у каждого четвертовложенного пункта придется делать 4 запроса... да?
27. egir - 25 Августа, 2011 - 11:23:44 - перейти к сообщению
Только учтите одно, что пока у вас пара сотней записей в таблицах БД, то с одним запросом будет все хорошо. Но когда их будет нескольк тесяч, посмотрите потом на объем памяти занимаемой скриптом, который достает эти все записи в массив и умножите их на кол-во обращений к старнице и будете "приятно" обобьем RAM требуемой для такого удовольствия.

Суть басни такова что при большом количестве записей ни один из выше предложенных способов не подойдет, хотя все работают, нужно будет дерево связей.
28. EuGen - 25 Августа, 2011 - 11:23:45 - перейти к сообщению
Kubert пишет:
придется делать 4 запроса

Нет, не так. Зависит от степени разветвленности дерева. Чем больше у каждого узла потомков, тем больше будет запросов.
Например, при уровне вложенности 3, если у каждого узла по 8 потомков и корневых узлов тоже 3, это будет
3+8*3+8*8*3=219 запросов.

egir пишет:
будете обобьем RAM требуемой для такого удовольствия

Несоизмеримо мал. Даже при большом уровне вложенности и разветвленности вряд ли будут заняты хотя бы 4-5Mb так как приведенные данные не занимают много места.
Памяти может не хватить, если каждый узел хранит большие текстовые данные. Но запросами в таком случае делать еще хуже.
29. egir - 25 Августа, 2011 - 11:25:48 - перейти к сообщению
EuGen пишет:
Kubert пишет:
придется делать 4 запроса

Нет, не так. Зависит от степени разветвленности дерева. Чем больше у каждого узла потомков, тем больше будет запросов.
Например, при уровне вложенности 3, если у каждого узла по 8 потомков и корневых узлов тоже 3, это будет
3+8*3+8*8*3=219 запросов.


Ничего подобного, он подымается от потомка к родителю, а не собирает всех потомков родителя. Так что запросов будет ровно столько, какая глубина вложенности.
30. EuGen - 25 Августа, 2011 - 11:27:23 - перейти к сообщению
egir пишет:
от потомка к родителю, а не собирает всех потомков родителя

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

 

Powered by ExBB FM 1.0 RC1