Преобразовать массив в массив для меню

149
10 марта 2019, 06:40

есть массив данных полученных по Rest API Пытаюсь из этих данных сделать меню, но для этого нужно его преобразовать с учетом вложенности (думаю это делается циклом)

Перерыл интернет, везде рекурсия с обычными числовыми id, а у меня id это строка, сам пробовал делать через foreach, получилось это

 foreach ($elements as $item){
     $thisRef = &$ref[$item['objectId']];
     $thisRef['parent'] = &$item['parent'];
     $thisRef['name'] = $item['property']['ru']['value'];
     $thisRef['objectId'] = $item['objectId'];
     $thisRef['number'] = $item['number'];
   $thisRef['duration'] = $item['duration'];
     $thisRef['object'] = $item['object'];
     $thisRef['listorder'] = $item['listorder'];
    if($item['parent'] == 0) {
         $items[$item['objectId']] = &$thisRef;
    } else {
    $ref[$item['parent']]['child'][$item['objectId']] = &$thisRef;       

    }

  }

 print_r($items);

Написанный мною цикл работает плохо, он выводит ветку только до 2 уровня

массив $elements выкладываю ниже в print_r и var_export

[objectId] - это id элемента

[parent] - это родитель элемента, он ссылается на objectId родителя, если он пустой или равен 0 значит у него нет родителя

Большая просьба предложить решение с неограниченной вложенностью.

Желаю добра тому кто мне поможет.

Массив через print_r

   Array
    (
     [0] => Array
         (
             [parent] => D0384DBB-F67C-FE92-FF46-F192B3F83B00
             [created] => 1540568545112
             [element_id] => 
             [ownerId] => 
             [type] => 
             [duration] => 
             [number] => 1
             [start_time] => 
             [enable] => 
             [tiam] => 
             [listorder] => 1
             [quest_id] => E18A9589-6AB2-8304-FFFC-98C11314CD00
             [updated] => 1540569546246
             [value] => 
             [objectId] => 0DE56A96-9FA9-64E0-FFAB-97A246517200
             [object] => round
             [___class] => Elements
             [property] => Array
                 (
                     [ru] => Array
                         (
                             [language_code] => ru
                             [created] => 1540568545865
                             [lang_id] => 0E5BD427-7883-903C-FFDD-2309E2D79800
                             [element_id] => 0DE56A96-9FA9-64E0-FFAB-97A246517200
                             [quest_id] => E18A9589-6AB2-8304-FFFC-98C11314CD00
                             [type] => 
                             [ownerId] => 
                             [value] => Раунд
                             [updated] => 
                             [objectId] => C28EE86F-71BC-A6D3-FFF6-707638303500
                             [object] => round
                             [___class] => Elements_values
                         )
                 )
         )
     [1] => Array
         (
             [parent] => 
             [created] => 1540540322673
             [element_id] => 
             [ownerId] => 
             [type] => 
             [duration] => 
             [number] => 1
             [start_time] => 
             [enable] => 
             [tiam] => 
             [listorder] => 1
             [quest_id] => E18A9589-6AB2-8304-FFFC-98C11314CD00
             [updated] => 1540564573693
             [value] => 
             [objectId] => 4449513D-1CDD-00EA-FFDF-1947E4FDEA00
             [object] => team
             [___class] => Elements
             [property] => Array
                 (
                     [ru] => Array
                         (
                             [language_code] => ru
                             [created] => 1540540323417
                             [lang_id] => 0E5BD427-7883-903C-FFDD-2309E2D79800
                             [element_id] => 4449513D-1CDD-00EA-FFDF-1947E4FDEA00
                             [quest_id] => E18A9589-6AB2-8304-FFFC-98C11314CD00
                             [type] => 
                             [ownerId] => 
                             [value] => Команда
                             [updated] => 
                             [objectId] => 2B2C86CF-E1F8-5D2C-FF0E-1DB592CC7500
                             [object] => team
                             [___class] => Elements_values
                         )
                 )
         )
     [2] => Array
         (
             [parent] => F0BFCFFA-D8F7-B5BE-FF37-D92AE35BBD00
             [created] => 1540567572958
             [element_id] => 
             [ownerId] => 
             [type] => 
             [duration] => 
             [number] => 1
             [start_time] => 
             [enable] => 
             [tiam] => 
             [listorder] => 1
             [quest_id] => E18A9589-6AB2-8304-FFFC-98C11314CD00
             [updated] => 1540567674259
             [value] => 
             [objectId] => D0384DBB-F67C-FE92-FF46-F192B3F83B00
             [object] => stage
             [___class] => Elements
             [property] => Array
                 (
                     [ru] => Array
                         (
                             [language_code] => ru
                             [created] => 1540567573722
                             [lang_id] => 0E5BD427-7883-903C-FFDD-2309E2D79800
                             [element_id] => D0384DBB-F67C-FE92-FF46-F192B3F83B00
                             [quest_id] => E18A9589-6AB2-8304-FFFC-98C11314CD00
                             [type] => 
                             [ownerId] => 
                             [value] => Этап
                             [updated] => 
                             [objectId] => 4E694471-70B3-C12B-FF79-97895532DD00
                             [object] => stage
                             [___class] => Elements_values
                         )
                 )
         )
     [3] => Array
         (
             [parent] => 4449513D-1CDD-00EA-FFDF-1947E4FDEA00
             [created] => 1540565297592
             [element_id] => 
             [ownerId] => 
             [type] => 
             [duration] => 
             [number] => 1
             [start_time] => 
             [enable] => 
             [tiam] => 
             [listorder] => 1
             [quest_id] => E18A9589-6AB2-8304-FFFC-98C11314CD00
             [updated] => 1540565310503
             [value] => 
             [objectId] => F0BFCFFA-D8F7-B5BE-FF37-D92AE35BBD00
             [object] => route
             [___class] => Elements
             [property] => Array
                 (
                     [ru] => Array
                         (
                             [language_code] => ru
                             [created] => 1540565298342
                             [lang_id] => 0E5BD427-7883-903C-FFDD-2309E2D79800
                             [element_id] => F0BFCFFA-D8F7-B5BE-FF37-D92AE35BBD00
                             [quest_id] => E18A9589-6AB2-8304-FFFC-98C11314CD00
                             [type] => 
                             [ownerId] => 
                             [value] => Маршрут
                             [updated] => 
                             [objectId] => 9CD62B6E-EACF-2911-FF57-3FF369F2BE00
                             [object] => route
                             [___class] => Elements_values
                         )
                 )
         )
   )

Массив через var_export

array (
    0 => 
   array (
     'parent' => 'D0384DBB-F67C-FE92-FF46-F192B3F83B00',
     'created' => 1540568545112,
     'element_id' => NULL,
     'ownerId' => NULL,
     'type' => NULL,
     'duration' => NULL,
     'number' => '1',
     'start_time' => NULL,
     'enable' => NULL,
     'tiam' => NULL,
     'listorder' => '1',
     'quest_id' => 'E18A9589-6AB2-8304-FFFC-98C11314CD00',
     'updated' => 1540569546246,
     'value' => NULL,
     'objectId' => '0DE56A96-9FA9-64E0-FFAB-97A246517200',
     'object' => 'round',
     '___class' => 'Elements',
     'property' => 
     array (
       'ru' => 
       array (
         'language_code' => 'ru',
         'created' => 1540568545865,
         'lang_id' => '0E5BD427-7883-903C-FFDD-2309E2D79800',
         'element_id' => '0DE56A96-9FA9-64E0-FFAB-97A246517200',
         'quest_id' => 'E18A9589-6AB2-8304-FFFC-98C11314CD00',
         'type' => NULL,
         'ownerId' => NULL,
         'value' => 'Раунд',
         'updated' => NULL,
         'objectId' => 'C28EE86F-71BC-A6D3-FFF6-707638303500',
         'object' => 'round',
         '___class' => 'Elements_values',
       ),
     ),
   ),
   1 => 
   array (
     'parent' => NULL,
     'created' => 1540540322673,
     'element_id' => NULL,
     'ownerId' => NULL,
     'type' => NULL,
     'duration' => NULL,
     'number' => '1',
     'start_time' => NULL,
     'enable' => NULL,
     'tiam' => NULL,
     'listorder' => '1',
     'quest_id' => 'E18A9589-6AB2-8304-FFFC-98C11314CD00',
     'updated' => 1540564573693,
     'value' => NULL,
     'objectId' => '4449513D-1CDD-00EA-FFDF-1947E4FDEA00',
     'object' => 'team',
     '___class' => 'Elements',
     'property' => 
     array (
       'ru' => 
       array (
         'language_code' => 'ru',
         'created' => 1540540323417,
         'lang_id' => '0E5BD427-7883-903C-FFDD-2309E2D79800',
         'element_id' => '4449513D-1CDD-00EA-FFDF-1947E4FDEA00',
         'quest_id' => 'E18A9589-6AB2-8304-FFFC-98C11314CD00',
         'type' => NULL,
         'ownerId' => NULL,
         'value' => 'Команда',
         'updated' => NULL,
         'objectId' => '2B2C86CF-E1F8-5D2C-FF0E-1DB592CC7500',
         'object' => 'team',
         '___class' => 'Elements_values',
       ),
     ),
   ),
   2 => 
   array (
     'parent' => 'F0BFCFFA-D8F7-B5BE-FF37-D92AE35BBD00',
     'created' => 1540567572958,
     'element_id' => NULL,
     'ownerId' => NULL,
     'type' => NULL,
     'duration' => NULL,
     'number' => '1',
     'start_time' => NULL,
     'enable' => NULL,
     'tiam' => NULL,
     'listorder' => '1',
     'quest_id' => 'E18A9589-6AB2-8304-FFFC-98C11314CD00',
     'updated' => 1540567674259,
     'value' => NULL,
     'objectId' => 'D0384DBB-F67C-FE92-FF46-F192B3F83B00',
     'object' => 'stage',
     '___class' => 'Elements',
     'property' => 
     array (
       'ru' => 
       array (
         'language_code' => 'ru',
         'created' => 1540567573722,
         'lang_id' => '0E5BD427-7883-903C-FFDD-2309E2D79800',
         'element_id' => 'D0384DBB-F67C-FE92-FF46-F192B3F83B00',
         'quest_id' => 'E18A9589-6AB2-8304-FFFC-98C11314CD00',
         'type' => NULL,
         'ownerId' => NULL,
         'value' => 'Этап',
         'updated' => NULL,
         'objectId' => '4E694471-70B3-C12B-FF79-97895532DD00',
         'object' => 'stage',
         '___class' => 'Elements_values',
       ),
     ),
   ),
   3 => 
   array (
     'parent' => '4449513D-1CDD-00EA-FFDF-1947E4FDEA00',
     'created' => 1540565297592,
     'element_id' => NULL,
     'ownerId' => NULL,
     'type' => NULL,
     'duration' => NULL,
     'number' => '1',
     'start_time' => NULL,
     'enable' => NULL,
     'tiam' => NULL,
     'listorder' => '1',
     'quest_id' => 'E18A9589-6AB2-8304-FFFC-98C11314CD00',
     'updated' => 1540565310503,
     'value' => NULL,
     'objectId' => 'F0BFCFFA-D8F7-B5BE-FF37-D92AE35BBD00',
     'object' => 'route',
     '___class' => 'Elements',
     'property' => 
     array (
       'ru' => 
       array (
         'language_code' => 'ru',
         'created' => 1540565298342,
         'lang_id' => '0E5BD427-7883-903C-FFDD-2309E2D79800',
         'element_id' => 'F0BFCFFA-D8F7-B5BE-FF37-D92AE35BBD00',
         'quest_id' => 'E18A9589-6AB2-8304-FFFC-98C11314CD00',
         'type' => NULL,
         'ownerId' => NULL,
         'value' => 'Маршрут',
         'updated' => NULL,
         'objectId' => '9CD62B6E-EACF-2911-FF57-3FF369F2BE00',
         'object' => 'route',
         '___class' => 'Elements_values',
       ),
     ),
   ),
 )

На выходе мне нужно примерно такое:

Array (

 ......
     [4449513D-1CDD-00EA-FFDF-1947E4FDEA00] => Array
         (
             [parent] => 
             [name] => Команда
             [objectId] => 4449513D-1CDD-00EA-FFDF-1947E4FDEA00
             [number] => 1
             [duration] => 
             [object] => team
             [listorder] => 1
             [child] => Array
                 (
                     [F0BFCFFA-D8F7-B5BE-FF37-D92AE35BBD00] => Array
                         (
                             [parent] => 4449513D-1CDD-00EA-FFDF-1947E4FDEA00
                             [name] => Маршрут
                             [objectId] => F0BFCFFA-D8F7-B5BE-FF37-D92AE35BBD00
                             [number] => 1
                             [duration] => 
                             [object] => route
                             [listorder] => 1
                             [child]=> Array
                                            (
                                                [D0384DBB-F67C-FE92-FF46-F192B3F83B00] => Array
                                                    (
                                                        [parent] => F0BFCFFA-D8F7-B5BE-FF37-D92AE35BBD00
                                                        [name] => Этап
                                                        [objectId] => D0384DBB-F67C-FE92-FF46-F192B3F83B00
                                                        [number] => 1
                                                        [duration] => 
                                                        [object] => stage
                                                        [listorder] => 1
                                                    )

                             )

                         )
                 )
 ....
         )

 )
Answer 1

Правильно ли я понимаю, что проблема в связях parent_id? Нужно обойти массив, и по нему выстроить многоуровневое вложенное меню, через parent_id

Да, классический вариант тут рекурсия. Но проблема в том, что глубина стека в php как правило установлена в 512 элементов, т.е. это максимальный уровень вложенности рекурсии, при дефолтных настройках.

В любом случае настройки тут менять не вариант, т.к. теоретически глубина вложенности не ограничена, и может быть и миллион, и миллиард, и больше - никакой памяти не хватит.

Но программирование штука сугубо прикладная, и многие такие моменты в программировании обходятся не теоретически, а элементарными физическими ограничениями (как правило ограничениями железа) и здравым смыслом: для меню 512 уровней - это с головой, на практике меню как правило двухуровневое, редко трех, больше уже экзотика. 10 уровней наверное вообще нигде не встречается, т.к. такое меню уже элементарно неудобно - попробуйте полазить по такому, с ума сойдете.

Так что разумный ответ такой: пользуйтесь рекурсией, и не заморачивайтесь. Текстовые идентификаторы никак не помешают выстроить иерархию - даже html-код в качестве ключей можно использовать, это симметричный массив, ему все равно.

Можно обойтись и без рекурсии конечно, воспользовавшись do...while циклом, но это будет очень дорого стоить, для массива из тысячи элементов потребуется перебрать два миллиона элементов, для массива из миллиона элементов потребуется перебрать два триллиона элементов, плюс код получится очень запутанным.

Для меню такой велосипед изобретать явно не стоит.

Пример рекурсии https://repl.it/@tomasj/recirsionmenu

READ ALSO
Реализация кучи

Реализация кучи

Говорят, что динамическая память в программе выделяется в куче, а локальные переменные - в стекеЕсли с реализаций стека всё вроде бы понятно,...

195
Студия 2017, cmake и boost на remote машине

Студия 2017, cmake и boost на remote машине

Использую студию 2017 и 2 варианта ремоут машин (WSL и VirtualBox(Debian95))

129
Необычная функция main

Необычная функция main

Недавно увидел в программе следующую версию main функции:

172