Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I did research on this, and wasn't able to find an exact answer. Most of the questions/answers on here pertaining to this seem to be unfinished. If anyone knows of a finished solution similar to my question, please point me in that direction!

Here is my array:

Array
(
['home'] => Array
    (
        [0] => sub-home1
        [1] => sub-home2
    )

['about'] => Array
    (
        [0] => sub-about
        ['about2'] => Array
            (
                [0] => sub-sub-about
            )

    )

['staff'] => Array
    (
        [0] => sub-staff1
        [1] => sub-staff2
    )

['contact'] => contact
)

And here is what I would like to turn it into:

<ul>
    <li><a href="">home<a/>
        <ul>
            <li><a href="">sub-home1</a></li>
            <li><a href="">sub-home2</a></li>
        </ul>
    </li>
    <li><a href="">about<a/>
        <ul>
            <li><a href="">sub-about</a></li>
            <li><a href="">about2</a>
                <ul>
                    <li><a href="">sub-sub-about<a/></li>
                </ul>
            </li>
        </ul>
    </li>
    <li><a href="">staff<a/>
        <ul>
            <li><a href="">sub-staff1</a></li>
            <li><a href="">sub-staff2</a></li>
        </ul>
    </li>
    <li><a href="">contact<a/></li>
</ul>

The array will be dynamically generated, but will have a limit of 3 levels ex: about->about2->sub-sub-about. I tried going off of this question: PHP/MySQL Navigation Menu but they didn't really seem to come to a conclusion? I am familiar with foreach's whiles and for loops but I just can't seem to wrap my head around this one.

EDIT: Enzino, your code works!

share|improve this question
I think what you need here is a recursive function that parses the arrays. Sorry I can't (off the top of my head) give an example, but this is DEFINITELY one case where recursion is necessary. – Matt Jul 31 '12 at 19:06
Yeah I'm trying to find a good example, not many out there! – K_G Jul 31 '12 at 19:16
You want to find a DFS (depth-first search) algorithm and implement it to output the list. – Matt Jul 31 '12 at 19:17

4 Answers

up vote 1 down vote accepted

Here is my solution:

<?php

function MakeMenu($items, $level = 0) {
    $ret = "";
    $indent = str_repeat(" ", $level * 2);
    $ret .= sprintf("%s<ul>\n", $indent);
    $indent = str_repeat(" ", ++$level * 2);
    foreach ($items as $item => $subitems) {
        if (!is_numeric($item)) {
            $ret .= sprintf("%s<li><a href=''>%s<a/>", $indent, $item);
        }
        if (is_array($subitems)) {
            $ret .= "\n";
            $ret .= MakeMenu($subitems, $level + 1);
            $ret .= $indent;
        } else if (strcmp($item, $subitems)){
            $ret .= sprintf("%s<li><a href=''>%s<a/>", $indent, $subitems);
        }
        $ret .= sprintf("</li>\n", $indent);
    }
    $indent = str_repeat(" ", --$level * 2);
    $ret .= sprintf("%s</ul>\n", $indent);
    return($ret);
}

$menu = Array(
            'home' => Array("sub-home1", "sub-home2"),
            'about' => Array("sub-about", "about2" => Array("sub-sub-about")),
            'staff' => Array("sub-staff1", "sub-staff2"),
            'contact' => "contact"
        );

print_r($menu);

echo MakeMenu($menu);

?>
share|improve this answer
Enzino, see edit above. Your code is not putting the sub items under their appropriate "parents" – K_G Jul 31 '12 at 19:46
I've slightly modified the code; please try again and let me know if now it works as expected. – Enzino Jul 31 '12 at 19:55
Thank you very much sir! I was on page 5 of google trying to find a good example. But your solution works. Now I have learned something new! – K_G Jul 31 '12 at 19:59

I think you can use recursion? Here is some pseudocode, not very familiar with php.

function toNavMenu(array A){
    for each element in A{
        echo "<li><a href=\"\">" + element.name + "</a>"
        if (element is an array){
            echo "<ul>"
            toNavMenu(element)
            echo "</ul>"
        }
        echo "</li>"
    }
}
share|improve this answer

Calvin's solution worked for me. Here's the edited version. We can use more nested loops to get sub - sub menu items.

echo '<ul>';
foreach ($menu as $parent) {

    echo '<li><a href="#">' . $parent . '</a>';

    if (is_array($parent)) {
        echo '<ul>';
            foreach ($parent as $children) {
                echo '<li><a href="#">' . $children . '</a>';
            }
        echo '</ul>';
    }

    echo '</li>';
}
echo '</ul>';
share|improve this answer
consider offering a recursive method – NewAlexandria Nov 12 '12 at 17:51

I would probably slightly adapt the array to be something like the following:

Array(
    0 => Array(
        'title' => 'Home',
        'children' => Array()
    ),
    1 => Array(
        'title' => 'Parent',
        'children' => Array(
            0 => Array(
                'title' => 'Sub 1',
                'children' => Array(),
            ),
            1 => Array(
                'title' => 'Sub 2',
                'children' => Array(
                    0 => Array(
                        'title' => 'Sub sub 2-1',
                        'children' => Array(),
                    ),
                ),
            ),
        )
    )
) 

With a structure like this you could use recursion to build your menu HTML:

function buildMenu($menuArray)
{
    foreach ($menuArray as $node)
    {
        echo "<li><a href='#'/>" . $node['title'] . "</a>";
        if ( ! empty($node['children'])) {
            echo "<ul>";
            buildMenu($node['children']);
            echo "</ul>";
        }
        echo "</li>";
    }
}
share|improve this answer
I tried your demo and it isn't outputting anything. – K_G Jul 31 '12 at 19:21
I fed the array to the function below (modified it first) and it works for me now. Please do note I only did a simple test. The rest of the programming is up to you :) – hoppa Jul 31 '12 at 19:35
Duh sorry! Had it the other way – K_G Jul 31 '12 at 19:39

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.