Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Рекурсия при выборки из БД


Автор: supercelt 12.12.2010, 16:01
Пишу для жумлы выборку секций и категорий из бд, в виде дерева. В таблице категорий есть поле parent_id но оно не задействовано. Но вот хотелось бы его использовать.
Я написал функцию, кторая работает, но с рекурсией, нет. 

Если убрать строчку $return .= getParentTree($listing->c_parent); то всё выводит, но только родителей. А если строку не убирать, вместо сайта вообще белый экран. В чём тут ошибка?

Код

    function getParentTree($parent){
    $return = '';
    $query = 'SELECT `s`.`id` AS `s_id`, `s`.`title` AS `s_title`, `c`.`id` AS `c_id`, `c`.`parent_id` AS `c_parent`, `c`.`title` AS `c_title` 
    FROM `#__sections` AS `s` 
    LEFT JOIN `#__categories` AS `c` ON `s`.`id` = `c`.`section` 
    WHERE `c`.`parent_id` = '.$parent.'
    GROUP BY `s_id`, `s_title`, `c_id`, `c_title`;';
    $db =& JFactory::getDBO();                                    
    $db->setQuery($query);
    $rows = $db->loadObjectList();
    $no_repeat_section = '';
        foreach($rows as $listing){
            if($listing->s_title == $no_repeat_section){
            $return .= "<li class=\"expandable\"><a class=\"cattree\" href=\"".JRoute::_(ContentHelperRoute::getCategoryRoute($listing->c_id, $listing->s_id))."\"> ".$listing->c_title."</a>".$listing->c_parent."</li>\n";
            }else{
            $return .= ($trigger == 1 ? "</ul>\n" : "")."<li class=\"expandable\"><a class=\"cattree\" href=\"".JRoute::_(ContentHelperRoute::getSectionRoute($listing->s_id))."\"> ".$listing->s_title."</a>\n<ul><li class=\"expandable\"><a class=\"cattree\" href=\"".JRoute::_(ContentHelperRoute::getCategoryRoute($listing->c_id, $listing->s_id))."\"> ".$listing->c_title."</a>".$listing->c_parent."</li>";
            $trigger = 1;
            }
        $no_repeat_section = $listing->s_title;
        $return .= getParentTree($listing->c_parent);
        }
    return $return;
    }

Автор: SneG0K 12.12.2010, 19:36
У тебя скрипт уходит в бесконечную рекурсию и умирает бедняга...

Лучше извлеки все записи из БД (один запрос), а потом на основе всех данных построй дерево и закешируй его.


Автор: supercelt 12.12.2010, 19:47
Я это как раз и пытался сделать. Решил, что надо одним запросом всё изъять и в массив это. А потом работать уже с массивом.
После изъятия из базы получилось вот что:

Это в $array

Код

Array ( 
[0] => Array ( 
    [s_id] => 5 
    [s_title] => Контент сайта 
    [c_id] => 34 
    [c_parent] => 0 
    [c_title] => Контент сайта 
    ) 
[1] => Array ( 
    [s_id] => 6 
    [s_title] => Статьи 
    [c_id] => 35 
    [c_parent] => 0 
    [c_title] => Web дизайн 
    ) 
[2] => Array ( 
    [s_id] => 6 
    [s_title] => Статьи 
    [c_id] => 36 
    [c_parent] => 0 
    [c_title] => Web программирование 
    ) 
[3] => Array ( 
    [s_id] => 6 
    [s_title] => Статьи 
    [c_id] => 37 
    [c_parent] => 36 
    [c_title] => PHP 
    ) 
[4] => Array ( 
    [s_id] => 6 
    [s_title] => Статьи 
    [c_id] => 38 
    [c_parent] => 0 
    [c_title] => JavaScript 
    ) 
[5] => Array ( 
    [s_id] => 6 
    [s_title] => Статьи 
    [c_id] => 39 
    [c_parent] => 0 
    [c_title] => MySQL 
    ) 
[6] => Array ( 
    [s_id] => 6 
    [s_title] => Статьи 
    [c_id] => 40 
    [c_parent] => 0 
    [c_title] => Joomla 
    ) 
) 


И теперь я работаю с массивом

Код

function getParentTree2($array, $parent = 0){
    $no_repeat_section = '';
        foreach($array as $row){
            if($row['c_parent'] == $parent){
                if($row['s_title'] == $no_repeat_section){
                $res .= '--'.$row['c_title'].'(parent->'.$row['c_parent'].')<br />';
                } else {
                $res .= $row['s_title']."<br />--".$row['c_title']."(parent->".$row['c_parent'].")<br />";
                }
            $no_repeat_section = $row['s_title'];
            $res .= modTreeSC::getParentTree2($array, $row['c_parent']);    
            }                
        }
    return $res;    
    }


А страница была белая потому что вместо getParentTree2($array, $row['c_parent']) нужно было modTreeSC::getParentTree2($array, $row['c_parent'])

но проблеам та же, теперь вместо белого экрана браузер просто сбрасывает соединение, как буд-то хоста нет. Если убрать $res .= modTreeSC::getParentTree2($array, $row['c_parent']);    то всё норм. Не понимаю где ошибка. Например в модуле mainmenu сделана такая же рекурсия, однако там всё работает

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)