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 Answers 2
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);
}
-
Thanks Andrew, this helped, voting +1, I'll post the correct answer.Ibrahim Azhar Armar– Ibrahim Azhar Armar2016年09月24日 08:07:54 +00:00Commented Sep 24, 2016 at 8:07
-
1Glad i could help. Sometimes custom recurive scripts is the easiest way.AndrewL– AndrewL2016年09月24日 08:15:26 +00:00Commented Sep 24, 2016 at 8:15
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);
RecursiveArrayIterator
would seem a good choice perhaps