ФорумПрограммированиеPHP для идиотов → Рекурсия ломает мозг

Рекурсия ломает мозг

  • seyfer

    Сообщения: 13 Репутация: N Группа: Кто попало

    Spritz 24 мая 2012 г. 9:46

    Добрый день, форумчане. Помогите пожалуйста работать код с рекурсией так, как я хочу. Второй день ломаю голову.
    Есть БД. В ней item имеет id и pid для древовидной структуры. Вот как раз и пытаюсь написать ф-ю такую, что бы база преображалась в вид:

    array
                   0 => 
                     ( 'id_item' => 134,
                      'pid' => 0,
                      'child' => 
                             array
                                  0 =>
                                       ( 'id_item' => 33,
                                         'pid' => 134
                                         'child' => 
                                                array
                                                    0 =>
    


    И так далее. Т.е. элементы имеющие pid равный родительскому id вкладываются в него как массив в поле child. И так до бесконечности, пока есть child для родительского id.

    Вот код. Вкладывается только 2 уровня, а третий уже пишется в первый.
    
    public function tree_items2($pid = 0) {
    
            //todo переписать
    
            $object = array();
    
            $this->pid = $pid;
    
            $query = "SELECT *
                    FROM " . $this->DB->tbl_prefix . "sklad_items
                    WHERE pid = :pid
                    ORDER BY name";
    
            $object['pid'] = $this->pid;
    
            $result = $this->DB->Select($query, $object);
    
            if ($result) {
                $i = 0;
                foreach ($result as $row) {
    
                    $c_object = array();
    
                    $c_query = "SELECT *
                        FROM " . $this->DB->tbl_prefix . "sklad_items AS items
                        WHERE items.pid = :id_item";
    
                    $c_object['id_item'] = $row['id_item'];
    
                    $items_child = $this->DB->Select($c_query, $c_object);
    
                    if ($items_child[0]['id_item'] > 0) {
    
                        $row['child'] = $items_child;
                        $this->items[] = $row;
    
                        $this->tree_items2($items_child[0]['id_item']);
                    } else {
    
                        $this->items[] = $row;
                    }
                }
            } else {
                return false;
            }
    
            return $this->items;
        }
    


    Проблема вот тут:
    else {
    
                        $this->items[] = $row;
                    }


    Тут должна быть запись в child предыдущего элемента. Но как сохранить путь до этого элемента для записи - ума не приложу.
  • Nyaah

    Сообщения: 574 Репутация: N Группа: Джедаи

    Spritz 24 мая 2012 г. 10:15, спустя 29 минут 26 секунд

  • seyfer

    Сообщения: 13 Репутация: N Группа: Кто попало

    Spritz 24 мая 2012 г. 11:47, спустя 1 час 31 минуту 44 секунды

    Благодарю за ссылки. У меня получается способ Списки смежности. Пока что прикрутил dtree отсюда http://www.activex.net.ru/docs/phpdtree.shtml, но хочется получать на выходе массив с вложениями, а в шаблоне использовать рекурсию с помощью смарти.
    Буду копать..
  • Nyaah

    Сообщения: 574 Репутация: N Группа: Джедаи

    Spritz 24 мая 2012 г. 14:31, спустя 2 часа 43 минуты 53 секунды

    хочется получать на выходе массив с вложениями

    function fetchTree(PDO $db)
    {
    	$dataSet = array();
    	$stmt = $db->prepare('SELECT "id", "parent_id" AS "parentId", "title" FROM "test"');
    	$stmt->execute();
    	while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    		$dataSet[$row['id']] = $row;
    		$dataSet[$row['id']]['children'] = array();
    	}
    	return buildTree($dataSet);
    }
    
    function buildTree($elements)
    {
    	$result = array();
    	foreach ($elements as $id => $value) {
    		if ($value['parentId'] > 0 && isset($elements[$value['parentId']])) {
    			$elements[$id]['parent'] =& $elements[$value['parentId']];
    			$elements[$value['parentId']]['children'][] =& $elements[$id];
    		}
    		else {
    			$result[$id] =& $elements[$id];
    		}
    	}
    	return $result;
    }
    
    $db = new PDO('pgsql:dbname=database;host=localhost', 'username', 'password');
    var_dump(fetchTree($db));
    Work, buy, consume, die
  • Ivan

    Сообщения: 1316 Репутация: N Группа: Адекваты

    Spritz 25 мая 2012 г. 3:47, спустя 13 часов 15 минут 32 секунды


    хочется получать на выходе массив с вложениями

    $stmt = $db->prepare('SELECT "id", "parent_id" AS "parentId", "title" FROM "test"');



    А в чем тут смысл prepare, лишний код
  • seyfer

    Сообщения: 13 Репутация: N Группа: Кто попало

    Spritz 25 мая 2012 г. 7:50, спустя 4 часа 2 минуты 55 секунд

    Nyaah, отлично! благодарю за код. Собирался переписывать отсюда так же на пдо.

    http://phpclub.ru/faq/Tree/AlLoadAll?v=i3b

    Вроде на этом методе и основано, если не ошибаюсь?



    А в чем тут смысл prepare, лишний код


    Вообще-то не лишний. Prepare и bindParam надо, иначе инъекция проходит. То, что PDO само экранирует имхо миф. Я даже где-то в английской доке читал фразу, типа "По идее пдо должен экранировать запрос автоматически". Как-то так была построена фраза, вроде даже на php.net. Может отсюда и пошло, что можно сразу exec и execute, а гарантий ни кто получается и не давал.
    Говорят, что там же в execute выполняются эти же методы (Prepare и bindParam). Хорошо, зачем их тогда выносить в PDO в пользование?
  • seyfer

    Сообщения: 13 Репутация: N Группа: Кто попало

    Spritz 25 мая 2012 г. 8:11, спустя 21 минуту 42 секунды

    Хотя в запросе нет параметров, тогда не нужен.

  • Nyaah

    Сообщения: 574 Репутация: N Группа: Джедаи

    Spritz 25 мая 2012 г. 10:22, спустя 2 часа 11 минут 11 секунд

    Из за 1 лишней строки кирпичей навалили =)
    Я всегда юзаю стейтменты, вдруг в дальнейшем понадобится добавить параметры в запрос
    Work, buy, consume, die
  • seyfer

    Сообщения: 13 Репутация: N Группа: Кто попало

    Spritz 28 мая 2012 г. 5:21, спустя 2 дня 18 часов 58 минут


    Из за 1 лишней строки кирпичей навалили =)
    Я всегда юзаю стейтменты, вдруг в дальнейшем понадобится добавить параметры в запрос


    Вы еще не видели сколько кирпичей тут навалили. Создавал такую же тему.
    http://phpclub.ru/talk/threads/%D0%A0%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D1%8F-%D0%BB%D0%BE%D0%BC%D0%B0%D0%B5%D1%82-%D0%BC%D0%BE%D0%B7%D0%B3.72198/

Пожалуйста, авторизуйтесь, чтобы написать комментарий!