0

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);
2
  • What fails in this code? Is there any error shown? The list isn't ordered correctly? Which is the output? Commented Dec 22, 2015 at 18:26
  • $parent is not defined, and you are treating $list[$menu['menu_id']] as a string. You should see errors. Commented Dec 22, 2015 at 18:57

1 Answer 1

2

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>
Sign up to request clarification or add additional context in comments.

3 Comments

@trincot the output of your function ain't correct, the li elements are not closed.
@ThomasScheffer, thanks for spotting this in my 2.5 year old answer :) Fixed now.
It showed up on the interesting tab for top question just now, guess because of the previous comment. np anyway :D

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.