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

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

  • seyfer

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

    Spritz 24 мая 2012 г. 1: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 г. 2:15, спустя 29 минут 26 секунд

  • seyfer

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

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

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

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

    Spritz 24 мая 2012 г. 6: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 24 мая 2012 г. 19:47, спустя 13 часов 15 минут 32 секунды


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

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



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

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

    Spritz 24 мая 2012 г. 23: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 г. 0:11, спустя 21 минуту 42 секунды

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

  • Nyaah

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

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

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

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

    Spritz 27 мая 2012 г. 21: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/

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