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.

asked Sep 24, 2016 at 7:30
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);
}
answered Sep 24, 2016 at 7:40
2
  • Thanks Andrew, this helped, voting +1, I'll post the correct answer. Commented Sep 24, 2016 at 8:07
  • 1
    Glad i could help. Sometimes custom recurive scripts is the easiest way. Commented Sep 24, 2016 at 8:15
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);
answered Sep 24, 2016 at 8:08

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.