Curious
Curious

Reputation: 103

Create n-level menu array from associative array

I want to create one n-level menu array from my php array. There can be n-level of children. The main array will be same means not a multidimensional n-level array. I've provided a sample array which meets the array structure I'm using.

$menu_array = 
Array
(
[menu-main] => Array
    (
        [menu_name] => Menu Name 1
        [menu_slug] => menu-main
        [parent_menu_slug] => 
    )
[menu-sub-main] => Array
    (
        [menu_name] => Sub Menu 1
        [menu_slug] => menu-sub-main
        [parent_menu_slug] => menu-main
    )
[menu-sub-sub-main] => Array
    (
        [menu_name] => Sub Sub Menu 1
        [menu_slug] => menu-sub-sub-main
        [parent_menu_slug] => menu-sub-main
    )
[menu-main1] => Array
    (
        [menu_name] => Menu Name 1
        [menu_slug] => menu-main1
        [parent_menu_slug] => 
    )
)

I want to create the n-level array to generate the menu from this array. To do so, I tried below

$x = [];
$tmp = array_combine(array_column($menu_array,'menu_slug'), $menu_array);

//parent menus only
foreach ($tmp as $k => $t) {
    if (empty($t['parent_menu_slug'])) {
        $x[$t['menu_slug']] = $t;
        unset($tmp[$k]);
    }
}

$d = [];
$rec_fn = function ($temp,$parent_slug = '') use (&$rec_fn,$x,&$d) {
    if ($parent_slug && array_key_exists($parent_slug,$x)) {
        $d[$parent_slug]['children'][] = $temp;
    } else {
        foreach ($temp as $c) {
            if (!empty($c['parent_menu_slug'])) {
                $d['children'][] = $rec_fn($c,$c['parent_menu_slug']);
            }
        }
    }
     return $d;
   };

$final_menu = $rec_fn($tmp);

But it is not returning the required result. The required result is

Array
(
[menu-main] => Array
    (
        [menu_name] => Menu Name 1
        [menu_slug] => menu-main
        [parent_menu_slug] => 
        [children] => array(
            [menu-sub-main] => Array
            (
                [menu_name] => Sub Menu 1
                [menu_slug] => menu-sub-main
                [parent_menu_slug] => menu-main
                [children] => array(
                    [menu-sub-sub-main] => Array
                    (
                        [menu_name] => Sub Sub Menu 1
                        [menu_slug] => menu-sub-sub-main
                        [parent_menu_slug] => menu-sub-main
                    )
                    .
                    .
                )
            )
            .
            .
        )
    )
[menu-main1] => Array
    (
        [menu_name] => Menu Name 1
        [menu_slug] => menu-main1
        [parent_menu_slug] => 
    )
..
)

Any help will be appreciated

Upvotes: 2

Views: 362

Answers (1)

Rahul
Rahul

Reputation: 18557

From link

I have made some function parameters changes as per requirement and to get exact output I changed branch line.

Here is the recursive function to achieve this,

function buildTree(array $elements, $options = [
    'parent_id_column_name' => 'parent_menu_slug',
    'children_key_name' => 'children',
    'id_column_name' => 'menu_slug'], $parentId = '')
    {
    $branch = array();
    foreach ($elements as $element) {
        if ($element[$options['parent_id_column_name']] == $parentId) {
            // we will call for every node which is having its child using recursion
            $children = buildTree($elements, $options, $element[$options['id_column_name']]);
            if ($children) { // if it have children array then save it
                $element[$options['children_key_name']] = $children;
            }
            // we will save every node's parent generated recursive data here
            $branch[$element['menu_slug']] = $element; // I changed this line
        }
    }
    // recursive generated data returned
    return $branch;
}

Here is working demo.

Upvotes: 1

Related Questions