0

I have following array, the depth of array cannot be known since array can have n childs.

$menu = [
    [
        'name' => 'home',
        'label' => 'Home',
        'uri' => '/home',
        'order' => 1,
        'attributes' => [
            'class' => ['home-class', 'home-class-2'],
            'id' => ['home-id']
        ]
    ], [
        'name' => 'about',
        'label' => 'About',
        'uri' => '/about',
        'order' => 2,
        'attributes' => [
            'class' => [],
            'id' => []
        ],
        'child' => [
            [
                'name' => 'company_profile',
                'label' => 'Company Profile',
                'uri' => '/company-profile',
                'order' => 1,
                'attributes' => [
                    'class' => [],
                    'id' => []
                ]
            ], [
                'name' => 'team',
                'label' => 'Team',
                'uri' => '/team',
                'order' => 2,
                'attributes' => [
                    'class' => ['team-class', 'team-class-2'],
                    'id' => ['team-id']
                ],
                'child' => [
                    [
                        'name' => 'management_team',
                        'label' => 'Management Team',
                        'uri' => '/management-team',
                        'order' => 1,
                        'attributes' => [
                            'class' => [],
                            'id' => []
                        ]
                    ],
                    [
                        'name' => 'development_team',
                        'label' => 'Development Team',
                        'uri' => '/development-team',
                        'order' => 2,
                        'attributes' => [
                            'class' => [],
                            'id' => []
                        ]
                    ],

                ]
            ],
        ]
    ], [
        'name' => 'services',
        'label' => 'Services',
        'uri' => '/services',
        'order' => 3,
        'attributes' => [
            'class' => [],
            'id' => []
        ],
        'child' => [
            [
                'name' => 'web_application',
                'label' => 'Web Application',
                'uri' => '/web-application',
                'order' => 1,
                'attributes' => [
                    'class' => [],
                    'id' => []
                ]
            ], [
                'name' => 'mobile_application',
                'label' => 'Mobile Application',
                'uri' => '/mobile-application',
                'order' => 2,
                'attributes' => [
                    'class' => [],
                    'id' => []
                ]
            ], [
                'name' => 'cms_development',
                'label' => 'CMS Development',
                'uri' => '/cms-development',
                'order' => 3,
                'attributes' => [
                    'class' => [],
                    'id' => []
                ]
            ],
        ]
    ]
];

I want to loop this over and pass data to object, for example.

$nav = new Navigation\Menu('main');
foreach ($menu as $item) {
    // Parent element
    $navItem = new Navigation\Item($item['name']);
    $navItem->setLabel($item['label']);
    $navItem->setUri($item['uri']);
    $nav->addItem($navItem);
    if (isset($item['child']) && is_array($item['child'])) {
        // First child
        foreach ($item['child'] as $child1) {
            $childItem1 = new Navigation\Item($child1['name']);
            $childItem1->setLabel($child1['label']);
            $childItem1->setUri($child1['uri']);
            $navItem->addChild($childItem1);
            if (isset($child1['child']) && is_array($child1['child'])) {
                // Second child
                foreach ($child1['child'] as $child2) {
                    $childItem2 = new Navigation\Item($child2['name']);
                    $childItem2->setLabel($child2['label']);
                    $childItem2->setUri($child2['uri']);
                    $childItem1->addChild($childItem2);
                }
            }
        }
    }
}

This works but with a problem. As you see, I am manually looping over each child, I do not want this, what i am looking for is, It must iterate the array recursively allowing to add any number of child with any depth.

I tried array_walk_recursive or custom recursive function without any result. any pointer to solve this is appreciated.

Thanks.

2
  • 1
    RecursiveArrayIterator would seem a good choice perhaps Commented Sep 24, 2016 at 7:38
  • I tried, the problem with using that is maintaining the child and depth when adding the element. Commented Sep 24, 2016 at 7:39

2 Answers 2

1

Here is a little recursive script that should run through every if it is an array or an object, each recursion will return the object. Now this would need some editing for your usage. But it should give you a starting point.

function Navigation($item) {
    if (is_object($item)) {
        foreach (get_object_vars($item) as $property => $value) {
            //If item is an object, then run recursively
            if (is_array($value) || is_object($value)) {
                $item->$property =  Navigation($item);
            } else {
                $navItem->setLabel($item['label']);
                $navItem->setUri($item['uri']);
                $nav->addItem($navItem);
            }
        }
        return $nav;
    } elseif (is_array($item)) {
        foreach ($item as $property => $value) {
            //If item is an array, then run recursively
            if (is_array($value) || is_object($value)) {
                $item[$property] =  Navigation($item);
            } else {
                $navItem->setLabel($item['label']);
                $navItem->setUri($item['uri']);
                $nav->addItem($navItem);
            }
        }
        return $nav;
    }
    $navItem->setLabel($item['label']);
    $navItem->setUri($item['uri']);
    $nav->addItem($navItem);
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Andrew, this helped, voting +1, I'll post the correct answer.
Glad i could help. Sometimes custom recurive scripts is the easiest way.
1

Figured it out finally.

Here is how i did it using custom recursive function.

function recursive($menu, &$nav, $child = false, $parent = null)
{
    foreach ($menu as $page) {
        $navItem = new Navigation\Item($page['name']);
        if (false == $child) {
            $nav->addItem($navItem);
        } else {
            $parent->addChild($navItem);
        }
        if (isset($page['child'])) {
            recursive($page['child'], $nav, true, $navItem);
        }
    }
}

$nav = new Navigation\Menu('main');
recursive($menu, $nav);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.