简体   繁体   中英

How to build tree structure from flat array

I have an array of menu items:

Array
(
    [0] => Joomla\CMS\Menu\MenuItem Object
        (
            [id] => 101
            [menutype] => mainmenu
            [title] => Home
            [alias] => home
            [note] => 
            [route] => home
            [link] => index.php?option=com_content&view=article&id=9
            [type] => component
            [level] => 1
            [language] => *
            [browserNav] => 0
            [access] => 1
            [home] => 1
            [img] =>  
            [template_style_id] => 0
            [component_id] => 22
            [parent_id] => 1
            [component] => com_content
            [tree] => Array
                (
                    [0] => 101
                )

            [query] => Array
                (
                    [option] => com_content
                    [view] => article
                    [id] => 9
                )

        )

    [1] => Joomla\CMS\Menu\MenuItem Object
        (
            [id] => 118
            [menutype] => mainmenu
            [title] => Legion Bohaterów
            [alias] => legion
            [note] => 
            [route] => legion
            [link] => index.php?Itemid=
            [type] => alias
            [level] => 1
            [language] => *
            [browserNav] => 0
            [access] => 1
            [home] => 0
            [img] =>  
            [template_style_id] => 0
            [component_id] => 0
            [parent_id] => 1
            [component] => 
            [tree] => Array
                (
                    [0] => 118
                )

            [query] => Array
                (
                    [Itemid] => 
                )

        )

    [2] => Joomla\CMS\Menu\MenuItem Object
        (
            [id] => 624
            [menutype] => mainmenu
            [title] => Dołącz do nas
            [alias] => dolacz-do-klubu
            [note] => 
            [route] => legion/dolacz-do-klubu
            [link] => index.php?option=com_content&view=category&layout=blog&id=10
            [type] => component
            [level] => 2
            [language] => *
            [browserNav] => 0
            [access] => 1
            [home] => 0
            [img] =>  
            [template_style_id] => 0
            [component_id] => 22
            [parent_id] => 118
            [component] => com_content
            [tree] => Array
                (
                    [0] => 118
                    [1] => 624
                )

            [query] => Array
                (
                    [option] => com_content
                    [view] => category
                    [layout] => blog
                    [id] => 10
                )

        )

    [3] => Joomla\CMS\Menu\MenuItem Object
        (
            [id] => 599
            [menutype] => mainmenu
            [title] => Wybierz upominki
            [alias] => wybierz-upominki
            [note] => 
            [route] => legion/dolacz-do-klubu/wybierz-upominki
            [link] => index.php?option=com_leg&view=upominki
            [type] => component
            [level] => 3
            [language] => *
            [browserNav] => 0
            [access] => 1
            [home] => 0
            [img] =>  
            [template_style_id] => 0
            [component_id] => 10069
            [parent_id] => 624
            [component] => com_leg
            [tree] => Array
                (
                    [0] => 118
                    [1] => 624
                    [2] => 599
                )

            [query] => Array
                (
                    [option] => com_leg
                    [view] => upominki
                )

        )

In tree element we have parents of element (where element should be attached). I made foreach function that looks like this:

    $mtree = array(); //new stdClass();
    foreach ($menuitems AS $i => $m)
        {
        if (sizeof($m->tree)==1) $mtree[$m->tree[0]]=(array)$m;
        elseif (sizeof($m->tree)==2) $mtree[$m->tree[0]]["c"][$m->tree[1]] = (array)$m;
        elseif (sizeof($m->tree)==3) $mtree[$m->tree[0]]["c"][$m->tree[1]]["c"][$m->tree[2]] = (array)$m;
        elseif (sizeof($m->tree)==4) $mtree[$m->tree[0]]["c"][$m->tree[1]]["c"][$m->tree[2]]["c"][$m->tree[3]] = (array)$m;
        elseif (sizeof($m->tree)==5) $mtree[$m->tree[0]]["c"][$m->tree[1]]["c"][$m->tree[2]]["c"][$m->tree[3]]["c"][$m->tree[4]] = (array)$m;
        }

but it is only for specific number of subtrees and it's not pretty. Any Idea how to do this recursively? (how to attach child to branch specified in array of parents).

The following functions can be used to print a tree that displays all the tree items and itself(the parent).

function getWithIdsAsKeys($menuItems) {
    $valuesByKey = [];

    foreach ($menuItems as $menuItem) {
        $valuesByKey[$menuItem->id] = $menuItem;
    }

    return $valuesByKey;
};

function printTree($allMenuItems, $menuItems, $depth = 0)
{
    foreach ($menuItems as $menuItem) {
        $prefix = str_repeat('        ', max(0, $depth - 1));
        $nestedSymbol = $depth === 0 ? '' :  '└─';
        echo $prefix . $nestedSymbol . $menuItem->id . '<br />';

        $subTree = array_map(function ($id) use ($allMenuItems, $menuItems) {
            return $allMenuItems[$id];
        }, array_filter($menuItem->tree, function ($id) use ($menuItem) {
            return $id !== $menuItem->id;
        }));

        printTree($allMenuItems, $subTree, $depth + 1);
    }
}
printTree(getWithIdsAsKeys($menuItems), getWithIdsAsKeys($menuItems));

result:

22
23
└─22
43
└─23
   └─22
44
└─43
   └─23
      └─22

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM