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

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Рекурсивная функция [2]

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


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

> Описание: почему то не "рекурсивица"...
egir
Отправлено: 25 Августа, 2011 - 00:17:46
Post Id



Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Авг. 2011  


Помог: 0 раз(а)




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

?
 
 Top
DeepVarvar Супермодератор
Отправлено: 25 Августа, 2011 - 00:20:13
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




CODE (SQL):
скопировать код в буфер обмена
  1. SELECT id,pid,name,idObject FROM tbl
 
 Top
egir
Отправлено: 25 Августа, 2011 - 10:02:39
Post Id



Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Авг. 2011  


Помог: 0 раз(а)




DeepVarvar пишет:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT id,pid,name,idObject FROM tbl


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



Частый гость


Покинул форум
Сообщений всего: 186
Дата рег-ции: Февр. 2010  


Помог: 3 раз(а)




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",
мне все равно придется при добавлении или обновлении страницы, необходимо будет запускать эту злосчастную функцию Ха-ха

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

Парни помогите, я уже замучился!

(Отредактировано автором: 25 Августа, 2011 - 10:37:03)

 
 Top
EuGen Администратор
Отправлено: 25 Августа, 2011 - 10:48:31
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Надеюсь, это поможет
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);


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
egir
Отправлено: 25 Августа, 2011 - 10:54:55
Post Id



Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Авг. 2011  


Помог: 0 раз(а)




Я раньше писал этот пример 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.  
 
 Top
Kubert
Отправлено: 25 Августа, 2011 - 11:09:47
Post Id



Частый гость


Покинул форум
Сообщений всего: 186
Дата рег-ции: Февр. 2010  


Помог: 3 раз(а)




egir
м-м-м... у меня не работает... пытаюсь чтото менять всеравно не работает...
 
 Top
egir
Отправлено: 25 Августа, 2011 - 11:10:57
Post Id



Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Авг. 2011  


Помог: 0 раз(а)




Kubert пишет:
egir
м-м-м... у меня не работает... пытаюсь чтото менять всеравно не работает...

а какая ошибка?
 
 Top
Kubert
Отправлено: 25 Августа, 2011 - 11:15:23
Post Id



Частый гость


Покинул форум
Сообщений всего: 186
Дата рег-ции: Февр. 2010  


Помог: 3 раз(а)




egir
В том то и дело никакой! просто пустой экран
(Добавление)
EuGen
буду разбираться, пробывать! Спасибо!
 
 Top
EuGen Администратор
Отправлено: 25 Августа, 2011 - 11:17:25
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Kubert
Выбирайте данные одним запросом в формате массива id - parent_id
Превратить его в древовидный можно потом (как - я описал в своем предыдущем комментарии).
С древовидной структурой затем можно уже будет делать что требуется. Вдобавок, это не потребует огромного количества запросов.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Kubert
Отправлено: 25 Августа, 2011 - 11:20:01
Post Id



Частый гость


Покинул форум
Сообщений всего: 186
Дата рег-ции: Февр. 2010  


Помог: 3 раз(а)




egir
И всеже если есть у нас уже имеется массив всех "категорий" с одним id потомком, то можно обойтись без запросов к БД. Это рациональнее. Так как к примеру у каждого четвертовложенного пункта придется делать 4 запроса... да?
 
 Top
egir
Отправлено: 25 Августа, 2011 - 11:23:44
Post Id



Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Авг. 2011  


Помог: 0 раз(а)




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

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

(Отредактировано автором: 25 Августа, 2011 - 11:26:33)

 
 Top
EuGen Администратор
Отправлено: 25 Августа, 2011 - 11:23:45
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Kubert пишет:
придется делать 4 запроса

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

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

Несоизмеримо мал. Даже при большом уровне вложенности и разветвленности вряд ли будут заняты хотя бы 4-5Mb так как приведенные данные не занимают много места.
Памяти может не хватить, если каждый узел хранит большие текстовые данные. Но запросами в таком случае делать еще хуже.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
egir
Отправлено: 25 Августа, 2011 - 11:25:48
Post Id



Новичок


Покинул форум
Сообщений всего: 16
Дата рег-ции: Авг. 2011  


Помог: 0 раз(а)




EuGen пишет:
Kubert пишет:
придется делать 4 запроса

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


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


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




egir пишет:
от потомка к родителю, а не собирает всех потомков родителя

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


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Страниц (4): « 1 [2] 3 4 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Хранение данных, их вывод и обработка »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB