Aunz HzOnos
Aunz HzOnos

Reputation: 37

Create a nested menu from an array

I am creating a function that should output a nested HTML menu from an array. I want to get the following output, but I get none:

Desired output

<ol class="sortable ui-sortable">
  <li id="list_77"><div>test1</div>
    <ol>
      <li id="list_78"><div>subtest1</div>
        <ol>
            <li id="list_79"><div>subtest1-1</div></li>
        </ol>
      </li>
    </ol>               
  </li> 
</ol>

My Data.

$item

Array
(    
    [77] => Array
        (
            [menu_id] => 77
            [menu_name] => test1
            [menu_parent_id] => 0
            [menu_sort] => 1
            [menu_link] => 
            [menu_status] => 1
        )

    [78] => Array
        (
            [menu_id] => 78
            [menu_name] => subtest1
            [menu_parent_id] => 77
            [menu_sort] => 1
            [menu_link] => 
            [menu_status] => 1
        )

    [79] => Array
        (
            [menu_id] => 79
            [menu_name] => subtest1-1
            [menu_parent_id] => 78
            [menu_sort] => 1
            [menu_link] => 
            [menu_status] => 1
        )
)

My Function

function sub($list) {

    foreach($list as $key => $menu){            
        echo '<li class="menu_list" id="item_'.$menu['menu_id'].'">';
        echo '<div>'.$menu['menu_id'].'-'.$menu['menu_name'].'-'.$list[$menu['menu_id']]."==".$parent.'</div>';

        if($list[$key]['menu_parent_id']!=$parent){
            echo '<ol>';
            echo $list[$key]['menu_parent_id'];
            echo '</ol>';
        } else {
            sub($list);
        }
        echo "</li>";
    }

}
$item = array();
echo sub($item);

Upvotes: 0

Views: 1351

Answers (1)

trincot
trincot

Reputation: 350079

You have some issues with recursion. You should pass to the sub function some context, i.e. for which menu item it should produce the sub-menu.

This also means that the function might not have to echo anything, i.e. when the passed menu item does not have any children.

So, for one, this means all your echo should be under some condition.

I would also suggest to make the function create and return an HTML string, which you can then echo. This makes the function more flexible to be used.

Here is the suggested code:

function sub($list, $parent_id = null) {
    $html = '';
    foreach ($list as $menu_id => $menu) {
        if ($list[$menu_id]['menu_parent_id'] == $parent_id) {
            $sub = sub($list, $menu_id);
            if ($sub != '') {
                // if there are children, wrap them in OL tag:
                $sub = "<ol>\n$sub</ol>\n";
            }
            // assemble HTML for this menu:
            $html .= "<li class='menu_list' id='item_{$menu['menu_id']}'>"
                  .  "<div>{$menu['menu_name']}</div>\n$sub</li>\n";
        }
    }
    return $html;
}

Here is how to use it:

// test data
$item = Array
(    
    77 => Array
        (
            "menu_id" => 77,
            "menu_name" => 'test1',
            "menu_parent_id" => 0,
            "menu_sort" => 1,
            "menu_link" => null,
            "menu_status" => 1
        ),
    78 => Array
        (
            "menu_id" => 78,
            "menu_name" => 'subtest1',
            "menu_parent_id" => 77,
            "menu_sort" => 1,
            "menu_link" => null,
            "menu_status" => 1,
        ),
    79 => Array
        (
            "menu_id" => 79,
            "menu_name" => 'subtest1-1',
            "menu_parent_id" => 78,
            "menu_sort" => 1,
            "menu_link" => null,
            "menu_status" => 1
        )
);

// Get complete output (no need to pass second argument)
echo sub($item); 

Output is as follows:

<li class='menu_list' id='item_77'><div>test1</div>
<ol>
<li class='menu_list' id='item_78'><div>subtest1</div>
<ol>
<li class='menu_list' id='item_79'><div>subtest1-1</div>
</li>
</ol>
</li>
</ol>
</li>

Upvotes: 2

Related Questions