Reputation: 664
I have been working on this for long and I got it working as I want but I think there is simpler solution.
So far I got this:
$menu = array(
0 => (object) array(
'cat_id' => 1,
'cat_parent' => 0,
'cat_name' => 'domov',
'cat_href' => 'domov',
'cat_subcategories' => array()
),
1 => (object) array(
'cat_id' => 2,
'cat_parent' => 0,
'cat_name' => 'clanky',
'cat_href' => 'clanky',
'cat_subcategories' => array(
0 => (object) array(
'cat_id' => 9,
'cat_parent' => 2,
'cat_name' => 'apple clanky',
'cat_href' => 'apple',
'cat_subcategories' => array(
0 => (object) array(
'cat_id' => 11,
'cat_parent' => 9,
'cat_name' => 'iphone clanky',
'cat_href' => 'iphone',
'cat_subcategories' => array()
),
1 => (object) array(
'cat_id' => 12,
'cat_parent' => 9,
'cat_name' => 'macbook clanky',
'cat_href' => 'macbook',
'cat_subcategories' => array()
)
)
),
1 => (object) array(
'cat_id' => 10,
'cat_parent' => 2,
'cat_name' => 'microsoft clanky',
'cat_href' => 'microsoft',
'cat_subcategories' => array()
),
)
),
2 => (object) array(
'cat_id' => 3,
'cat_parent' => 0,
'cat_name' => 'produkty',
'cat_href' => 'produkty',
'cat_subcategories' => array()
),
3 => (object) array(
'cat_id' => 4,
'cat_parent' => 0,
'cat_name' => 'vyrobcovia',
'cat_href' => 'vyrobcovia',
'cat_subcategories' =>
array(
0 => (object) array(
'cat_id' => 5,
'cat_parent' => 4,
'cat_name' => 'apple',
'cat_href' => 'apple',
'cat_subcategories' => array(
0 => (object) array(
'cat_id' => 7,
'cat_parent' => 5,
'cat_name' => 'iphone',
'cat_href' => 'iphone',
'cat_subcategories' => array()
),
1 => (object) array(
'cat_id' => 8,
'cat_parent' => 5,
'cat_name' => 'macbook',
'cat_href' => 'macbook',
'cat_subcategories' => array()
)
)
),
1 => (object) array(
'cat_id' => 6,
'cat_parent' => 4,
'cat_name' => 'microsoft',
'cat_href' => 'microsoft',
'cat_subcategories' => array()
),
)
),
);
function generate_menu($menu, $level = 1, $tmp_array = array())
{
foreach($menu as $key => $c)
{
$menu_item = get_menu_elements($c, $level);
$tmp_array = array_replace_recursive($tmp_array, $menu_item);
foreach($c->cat_subcategories as $_key => $_c)
{
$menu_item = get_menu_elements($_c, $level+1);
$tmp_array = array_replace_recursive($tmp_array, $menu_item);
foreach($_c->cat_subcategories as $__key => $__c)
{
$menu_item = get_menu_elements($__c, $level+2);
$tmp_array = array_replace_recursive($tmp_array, $menu_item);
}
}
}
return $tmp_array;
}
function get_menu_elements($c, $level = 1)
{
$level_var = "level_".($level);
$output = array(
$level_var => array()
);
$output[$level_var][$c->cat_id] = array(
'parent' => $c->cat_parent,
'html' => $c->cat_name
);
return $output;
}
In the end I should have multidimensional array with:
array(3) {
["level_1"]=>
array(4) {
[1]=>
array(2) {
["parent"]=>
int(0)
["html"]=>
string(5) "domov"
}
[2]=>
array(2) {
["parent"]=>
int(0)
["html"]=>
string(6) "clanky"
}
[3]=>
array(2) {
["parent"]=>
int(0)
["html"]=>
string(8) "produkty"
}
[4]=>
array(2) {
["parent"]=>
int(0)
["html"]=>
string(10) "vyrobcovia"
}
}
["level_2"]=>
array(4) {
[9]=>
array(2) {
["parent"]=>
int(2)
["html"]=>
string(12) "apple clanky"
}
[10]=>
array(2) {
["parent"]=>
int(2)
["html"]=>
string(16) "microsoft clanky"
}
[5]=>
array(2) {
["parent"]=>
int(4)
["html"]=>
string(5) "apple"
}
[6]=>
array(2) {
["parent"]=>
int(4)
["html"]=>
string(9) "microsoft"
}
}
["level_3"]=>
array(4) {
[11]=>
array(2) {
["parent"]=>
int(9)
["html"]=>
string(13) "iphone clanky"
}
[12]=>
array(2) {
["parent"]=>
int(9)
["html"]=>
string(14) "macbook clanky"
}
[7]=>
array(2) {
["parent"]=>
int(5)
["html"]=>
string(6) "iphone"
}
[8]=>
array(2) {
["parent"]=>
int(5)
["html"]=>
string(7) "macbook"
}
}
}
I want to print multi-level menu recursion. I got it working with this code but in function generate_menu I had to use 3 foreach loops for cat_subcategories. When I used recursion like this:
function generate_menu($menu, $level = 1, $tmp_array = array())
{
foreach($menu as $key => $c)
{
$menu_item = get_menu_elements($c, $level);
$tmp_array = array_replace_recursive($tmp_array, $menu_item);
if (!empty($c->cat_subcategories)) generate_menu($c->cat_subcategories, $level + 1, $tmp_array);
}
return $tmp_array;
}
i got only 'level_1' in output
The output which I am getting now is the same I want I just want to simplify the multiple foreach()
etc. Basicaly
level_1 - first loop of $menu level_2 - loop of cat_subcategories level_3 - loop of cat_subcategories for cat_subcategories item
Upvotes: 2
Views: 1167
Reputation: 351218
You essentially need to perform a breadth-first traversal in your menu tree. For that I would suggest an iterative function instead of a recursive function, as the latter is more suitable for a depth-first traversal.
Here is the function:
function generate_menu($menu) {
$result = [];
$level = 1;
while (count($menu)) {
$queue = [];
$items = [];
foreach($menu as $cat) {
$items[$cat->cat_id] = [
"parent" => $cat->cat_parent,
"html" => $cat->cat_name
];
$queue = array_merge($queue, $cat->cat_subcategories);
}
$result["level_$level"] = $items;
$level++;
$menu = $queue;
}
return $result;
}
See it run on eval.in.
As this function traverses the top level of the tree, it collects all the children into $queue
. Once the top level has been translated into the output (in the level_1
key), that queue will have all second level entries. This then is moved to $menu
, and the process is repeated, but now with level_2
. This continues until a level is reached where no more entries are found.
Upvotes: 2
Reputation: 3580
CODE TO PRINT MENU
This code will work for N-number of hierarchy
static function printAllCategoriesAsCheckbox($arr, $d=0){
$htmlString = "";
if (is_array($arr)){
foreach($arr as $category){
$htmlString = $htmlString . '<div><input style="margin-left: ' . 30*$d . 'px;" value="'.$category->id.'" class="category-input" type="checkbox" name="category_id[]">';
$htmlString = $htmlString . ' <label for="category_'.$category->id.'">' . $category->name . '</label></div>';
if (is_array($category['childs'])){
$htmlString = $htmlString . ItemCategory::printAllCategoriesAsCheckbox($category['childs'], $d+1);
}
}
}
return $htmlString;
}
Upvotes: 0
Reputation: 2483
I've made some time ago this function. It could help you.
I've got an array where $arr[actual item][parental id]
function getChild($id, $result, $count) {
for( $i = 0; $i < sizeof($result); $i ++) {
if( $result[$i][2] == $id) {
getChild($result[$i][0], $result, $count + 1);
}
}
}
In my case, where all the items in the one-dimensional array, but with the hierarchy of n-dimensional array depended on the parental id.
Upvotes: 0