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 :: Версия для печати :: Рекурсивная функция
Форумы портала PHP.SU » » Хранение данных, их вывод и обработка » Рекурсивная функция

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

1. Kubert - 24 Августа, 2011 - 14:16:57 - перейти к сообщению
Функция должна искать своих "предков" до корневого(т.е. со значение родителя равного "0"), записывать в массив их idObject...

Примерно картина из БД такая:
CODE (htmlphp):
скопировать код в буфер обмена
  1. id | pid | name | idObject
  2. 1 | 0 | Категория 1 | 111
  3. ...
  4. 3 | 1 | Категория 1.1 | 222
  5. ...
  6. 10 |3 | Категория 1.1.1 | 333
  7. ...
  8. 45 | 10 | Категория 1.1.1.1 | 444
  9. ...



Функция должна выводить примерно такое:
CODE (htmlphp):
скопировать код в буфер обмена
  1. $listId = array(444,333,222,111)



Массив $fintParent такого вида:
CODE (htmlphp):
скопировать код в буфер обмена
  1. $fintParent = array(
  2.     id => 1,
  3.     pid => 0,
  4.     name => Категория 1,
  5.     idObject => 111
  6. );



Сама функция
CODE (htmlphp):
скопировать код в буфер обмена
  1. function find($fintParent,$id,$listId){
  2.         $listId = array();
  3.         if($fintParent[$id]['pid'] != 0){
  4.                 $listId[] = $fintParent[$id]['pid'];
  5.                 find($fintParent,$fintParent[$id]['pid'],$listId);
  6.         }
  7.         return $listId;
  8. }
  9. print_r(find($fintParent,45));
  10.  


Где ошибка?
Сейчас заносит в массив только одного (первого) родителя...
2. Мелкий - 24 Августа, 2011 - 14:26:30 - перейти к сообщению
Вы ничего не делаете со значением, которое вызывает рекурсивная функция.
3. Kubert - 24 Августа, 2011 - 14:31:52 - перейти к сообщению
Мелкий
Как же?
Я ищу в многомерном массиве $fintParent его родителя и добавляю в массив $listId значение $idObject
вот вроде: $listId[] = $fintParent[$id]['pid'];

Разве нет? А потом снова вызываю эту функцию но с уже id родителя и так до бесконечности пока родитель не будет равен "0"
4. DeepVarvar - 24 Августа, 2011 - 15:15:46 - перейти к сообщению
Kubert пишет:
родитель не будет равен "0
вот только начинать надо наоборот с нуля Закатив глазки
5. Мелкий - 24 Августа, 2011 - 15:19:19 - перейти к сообщению
Kubert, не знаю, что вы там предполагаете, но в объявлении функции вы полностью игнорируете то, что вернула рекурсивная функция.
6. Kubert - 24 Августа, 2011 - 15:24:15 - перейти к сообщению
Мелкий
Что же она вернула и как я игнорирую это... Можете пояснить?

DeepVarvar
Мне из предыдущей функции(ее здесь нет), известен только id который я передаю в этой функции. А эта функция мне как раз помогает найти всех предков этого id...

Я явно запутался Однако
7. Мелкий - 24 Августа, 2011 - 16:52:23 - перейти к сообщению
Kubert пишет:
строка 5: find($fin...

Тогда как функция результат своей работы возвращает через return. Т.о. отрабатывает зря.
8. Champion - 24 Августа, 2011 - 16:56:24 - перейти к сообщению
Мелкий пишет:
вы полностью игнорируете то, что вернула рекурсивная функция.
Ну в принципе можно это и игнорировать. Здесь выход происходит не по возвращаемому значению, а по переданному параметру - это тоже жизнеспособно.

Kubert, ошибка в том, что измененкения, произошедшие во внутренних find() не отражаются во внешней. Нужно либо $listId передавать по ссылке, либо возвращать его и пользоваться
9. Kubert - 24 Августа, 2011 - 17:17:50 - перейти к сообщению
Champion
Не понимаю...

Мог бы ты привести код для данного примера.

Я же перед тем как вызвать внутренний find() присваиваю значение массиву...
А потом при запуске find() передаю его дальше и так пока функция не дойдет до конца.
Т.е. массив постоянно новый должен передаваться в функцию...
А когда функция закончина, то уже полностью сформированный массив передаю "ретурном".
Разве не так?
10. Champion - 24 Августа, 2011 - 18:23:53 - перейти к сообщению
Kubert пишет:
Мог бы ты привести код для данного примера.
Проще всего в объявлении функции поставить & перед последним параметром.

Kubert пишет:
Я же перед тем как вызвать внутренний find() присваиваю значение массиву...
да...
Kubert пишет:
А потом при запуске find() передаю его дальше и так пока функция не дойдет до конца.
Т.е. массив постоянно новый должен передаваться в функцию...
тоже да...
Kubert пишет:
А когда функция закончина, то уже полностью сформированный массив передаю "ретурном".
А тут нет. Полностью сформированный массив будет только внутри самой внутренней функции. Для более внешней функции массив останется без изменений. Ретурном вы его не передаете. Значение функции ничему не присваивается.
Чтоб понять что как происходит, напишите, напримеp var_dump($listId) до и после внутреннего вызова find и посмотрите, что выводит. Только не спутайте вывод того что до и того, что после, а то сделаете не те выводы
11. DeepVarvar - 24 Августа, 2011 - 18:24:06 - перейти к сообщению
Kubert я вот не понимаю зачем делать потом лишний цикл?
Ну вот сформировали мы этот промежуточный массив со всеми вложенностями.
И что дальше? При выводе еще раз перебирать с условиями?
Нафига? Перебирайте один раз - сразу в результирующую хтмл-разметку ул ли или что там будет...
(Добавление)
PHP:
скопировать код в буфер обмена
  1. function buildTree(&$arr,$parent = 0) {
  2.   $out = "";
  3.   if (is_array($arr) and count($arr) > 0) {
  4.     foreach ($arr as $item) {
  5.       if ($item['parent'] == $parent) {
  6.         $childs = buildTree($arr,$item['id']);
  7.         $out .= '<li><a href="'.$item['link'].'">'.$item['name'].'</a>'.$childs.'</li>';
  8.         }
  9.       }
  10.     }
  11.   return ($out != "") ? "<ul>$out</ul>" : "";
  12.   }
  13.  
  14. // массив вида
  15. // $arr[n]['id'] - id записи
  16. // $arr[n]['parent'] - родитель
  17. // $arr[n]['link'] - ссылка
  18. // $arr[n]['name'] - имя
  19. // учитывая что у тех кто в корне parent = 0
  20. // вызываем так
  21.  
  22. echo buildTree($arr);
12. egir - 24 Августа, 2011 - 23:54:28 - перейти к сообщению
Реализация требуемого Вам метода, когда ф-ция возвращает массив:
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.  


У Вас в начале ф-ции find() находился код: $listId = array(); Этого нельзя делать, вы при кадой рекурсии обнуляли массив. Код набросал на быструю руку, могут быть ошибки.
13. DeepVarvar - 24 Августа, 2011 - 23:59:22 - перейти к сообщению
egir пишет:
//Запрос к БД, чтобы достать инфу о текущей категории
Оооо!!!! А если их 200 или 300 ???
14. egir - 25 Августа, 2011 - 00:02:58 - перейти к сообщению
DeepVarvar пишет:
egir пишет:
//Запрос к БД, чтобы достать инфу о текущей категории
Оооо!!!! А если их 200 или 300 ???


Ну человеку требовался именно массив. Я для таких случаев делаю таблицу, в которой содержатся все возможные связи от родителя к потомкам и потом одним запросом достаю все что мне надо. Правда при добавлении новой записи приходится переформировывать таблицу дерева связей, но лучше один раз. Хотя если в таблицах проставить индексы по айдишникам и так все будет летать.
15. DeepVarvar - 25 Августа, 2011 - 00:05:49 - перейти к сообщению
Так мой пример разбирает весь массив из одного запроса по вложеностям и ничего не нужно будет при добавлении нового пункта переформировывать.
Зачем крутить лишние циклы и запросы?

 

Powered by ExBB FM 1.0 RC1