Создание дерева категорий из массива

Тема в разделе "OpenCart", создана пользователем halfhope, 1 янв 2014.

  1. halfhope

    halfhope

    Регистрация:
    31 дек 2012
    Сообщения:
    285
    Симпатии:
    312
    Доброго времени суток и с Новым Годом.
    Помогите решить задачу, голову сломал, рекурсия тоже сломалась. P.S. Это для древовидных категорий в админке OpenCart. И это не велосипед, я знаю как работает такое же меню в ocStore.
    Получаю однородный массив категорий:
    'categories' => array
    0 =>
    array
    'category_id' => string '28'
    'parent_id' => string '25'
    'name' => string 'Monitors'
    1 =>
    array
    'category_id' => string '28'
    'parent_id' => string '25'
    'name' => string 'Monitors'

    У каждой категории есть parent_id и category_id, по которым мы можем их идентифицировать и прицепить к друг-другу в новом массиве. Главной (первого уровня) parent_id является 0. Необходимо создать из массива новый массив с деревом категорий.
    Если подумать, это легко для двухуровневого меню, а если меню многоуровневое? Я смотрел в сторону рекурсии, но не получилось.
    Прошу помощи у вас, объясните только логику работы, код напишу сам. Заранее спасибо.
    --- Добавлено, 1 янв 2014 ---
    На других языках программирования я бы справился лишь одним проходом по массиву, но тут не могу понять работу с указателями.
    --- Добавлено, 1 янв 2014 ---
    Решил задачу, для решения необходимо всего один раз пройтись по массиву и добавлять к каждой категории ссылку на дочерний элемент этого же массива. И никакой рекурсии. А для того, чтобы добавить все категории, у которых parent_id = 0 т.е. они содержатся в главной категории, необходимо было создать эту самую категорию, где category_id = 0 =)
    PHP:
                $cate[0]  = array('name'=>'root','category_id'=>0);
                foreach (
    $cate as $key => $value) {
                    if (isset(
    $value['parent_id'])) {
                        
    $cate[$value['parent_id']]['childs'][] = &$cate[$key];
                    }
                }
    --- Добавлено, 1 янв 2014 ---
    Получился вот такой массив
    Код:
    array (size=2)
      0 =>
        array (size=4)
          'store_id' => int 0
          'name' => string 'Your Store <b>(Default)</b>' (length=27)
          'url' => string 'http://1551.opencart.im/' (length=24)
          'categories' =>
            array (size=3)
              'name' => string 'root' (length=4)
              'category_id' => int 0
              'childs' =>
                array (size=8)
                  0 =>
                    array (size=4)
                      'parent_id' => string '0' (length=1)
                      'pattern_id' => string '0' (length=1)
                      'use_for_child' => string '0' (length=1)
                      'name' => string 'Cameras' (length=7)
                  1 =>
                    array (size=4)
                      'parent_id' => string '0' (length=1)
                      'pattern_id' => string '0' (length=1)
                      'use_for_child' => string '0' (length=1)
                      'name' => string 'Software' (length=8)
                  2 =>
                    array (size=5)
                      'parent_id' => string '0' (length=1)
                      'pattern_id' => string '1' (length=1)
                      'use_for_child' => string '0' (length=1)
                      'name' => string 'Components' (length=10)
                      'childs' =>
                        array (size=5)
                          0 =>
                            array (size=5)
                              'parent_id' => string '25' (length=2)
                              'pattern_id' => string '1' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'Monitors' (length=8)
                              'childs' =>
                                array (size=2)
                                  0 =>
                                    array (size=4)
                                      'parent_id' => string '28' (length=2)
                                      'pattern_id' => string '0' (length=1)
                                      'use_for_child' => string '0' (length=1)
                                      'name' => string 'test 1' (length=6)
                                  1 =>
                                    array (size=4)
                                      'parent_id' => string '28' (length=2)
                                      'pattern_id' => string '0' (length=1)
                                      'use_for_child' => string '0' (length=1)
                                      'name' => string 'test 2' (length=6)
                          1 =>
                            array (size=4)
                              'parent_id' => string '25' (length=2)
                              'pattern_id' => string '1' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'Web Cameras' (length=11)
                          2 =>
                            array (size=4)
                              'parent_id' => string '25' (length=2)
                              'pattern_id' => string '1' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'Scanners' (length=8)
                          3 =>
                            array (size=4)
                              'parent_id' => string '25' (length=2)
                              'pattern_id' => string '1' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'Printers' (length=8)
                          4 =>
                            array (size=4)
                              'parent_id' => string '25' (length=2)
                              'pattern_id' => string '1' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'Mice and Trackballs' (length=19)
                  3 =>
                    array (size=4)
                      'parent_id' => string '0' (length=1)
                      'pattern_id' => string '0' (length=1)
                      'use_for_child' => string '0' (length=1)
                      'name' => string 'Phones &amp; PDAs' (length=17)
                  4 =>
                    array (size=5)
                      'parent_id' => string '0' (length=1)
                      'pattern_id' => string '0' (length=1)
                      'use_for_child' => string '0' (length=1)
                      'name' => string 'Desktops' (length=8)
                      'childs' =>
                        array (size=2)
                          0 =>
                            array (size=4)
                              'parent_id' => string '20' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'Mac' (length=3)
                          1 =>
                            array (size=4)
                              'parent_id' => string '20' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'PC' (length=2)
                  5 =>
                    array (size=5)
                      'parent_id' => string '0' (length=1)
                      'pattern_id' => string '0' (length=1)
                      'use_for_child' => string '0' (length=1)
                      'name' => string 'MP3 Players' (length=11)
                      'childs' =>
                        array (size=18)
                          0 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 5' (length=6)
                          1 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 4' (length=6)
                          2 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 6' (length=6)
                          3 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 7' (length=6)
                          4 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 8' (length=6)
                          5 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 9' (length=6)
                          6 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 11' (length=7)
                          7 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 12' (length=7)
                          8 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 15' (length=7)
                          9 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 16' (length=7)
                          10 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 17' (length=7)
                          11 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 18' (length=7)
                          12 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 19' (length=7)
                          13 =>
                            array (size=5)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 20' (length=7)
                              'childs' =>
                                array (size=1)
                                  0 =>
                                    array (size=4)
                                      'parent_id' => string '52' (length=2)
                                      'pattern_id' => string '0' (length=1)
                                      'use_for_child' => string '0' (length=1)
                                      'name' => string 'test 25' (length=7)
                          14 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 21' (length=7)
                          15 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 22' (length=7)
                          16 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 23' (length=7)
                          17 =>
                            array (size=4)
                              'parent_id' => string '34' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'test 24' (length=7)
                  6 =>
                    array (size=5)
                      'parent_id' => string '0' (length=1)
                      'pattern_id' => string '0' (length=1)
                      'use_for_child' => string '0' (length=1)
                      'name' => string 'Laptops &amp; Notebooks' (length=23)
                      'childs' =>
                        array (size=2)
                          0 =>
                            array (size=4)
                              'parent_id' => string '18' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'Windows' (length=7)
                          1 =>
                            array (size=4)
                              'parent_id' => string '18' (length=2)
                              'pattern_id' => string '0' (length=1)
                              'use_for_child' => string '0' (length=1)
                              'name' => string 'Macs' (length=4)
                  7 =>
                    array (size=4)
                      'parent_id' => string '0' (length=1)
                      'pattern_id' => string '0' (length=1)
                      'use_for_child' => string '0' (length=1)
                      'name' => string 'Tablets' (length=7)
      1 =>
        array (size=4)
          'store_id' => int 1
          'name' => string 'Store 2' (length=7)
          'url' => string 'http://cdn1.opencart.im/' (length=24)
          'categories' => &
            array (size=3)
              'name' => string 'root' (length=4)
              'category_id' => int 0
              'childs' =>
                array (size=2)
                  0 => &
                    array (size=4)
                      'parent_id' => string '0' (length=1)
                      'pattern_id' => string '0' (length=1)
                      'use_for_child' => string '0' (length=1)
                      'name' => string 'Cameras' (length=7)
                  1 => &
                    array (size=4)
                      'parent_id' => string '0' (length=1)
                      'pattern_id' => string '0' (length=1)
                      'use_for_child' => string '0' (length=1)
                      'name' => string 'Desktops' (length=8)
    --- Добавлено, 1 янв 2014 ---
    Всем спасибо, сам задал - сам ответил =)
     
    Последнее редактирование: 1 янв 2014
  2. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    2.051
    Симпатии:
    778
    Была у меня когда-то подобная задача, только я создавал дерево комментариев к товару (делал вместо стандартных комментариев нормальную систему для обсуждения товара).
    Я при сохранении дочерного элемента, добавлял к родителю указатель на наличие дочерных элементов (и, конечно, дочерному элементу вписывал id родителя). А при построении дерева проходил циклом по первому уровню комментариев (у которых нет родителей) и при наличии указателя на дочерные элементы, рекурсивно прочёсывал комментарии в их поиске. Рекурсиво потому, что при наличии у дочерного комментария указателя на дочерные элементы, заново вызывал функцию поиска потомков.
    В результате я получал многоуровневый массив, который полностью соответствовал дереву.
     
    halfhope нравится это.