1

I have a single array containing menu items. Each item have its parent_id. I am searching and trying for many hours but can't figure out how to traverse the array recursively. I'm not good at recursion.

I have tried to use the code from the following post. It generates the html menu but it misses the 1st record also I want an array so I can make custom html menu out of the array.

Using recursion to build navigation

I have tried this code from an other post but it returns empty array.

create_array(-1, $array);

function create_array($number, $data)
{
    $result = array();
    foreach ($data as $row)
    {
        if ($row['parent_id'] == $number)
        {
            $result[$row['id']] = create_array($row['id'], $data);
        }
    }
    return $result;
}

data array:

Array
(
    [0] => Array
        (
            [id] => 1
            [parent_id] => -1
            [url] => /home
        )

    [1] => Array
        (
            [id] => 2
            [parent_id] => 0
            [url] => /page
        )

    [2] => Array
        (
            [id] => 3
            [parent_id] => 2
            [url] => /page/sub_page
        )

    [3] => Array
        (
            [id] => 4
            [parent_id] => 3
            [url] => /page/sub_page/inner_page/
        )

)

result desired:

home - page
         sub_page
           inner_page

Any help will be very appreciated please.

3
  • @larsAnders actually, the data is from a single table with self referencing parent ids. id with 0 are non-child elements and -1 is the home page other willhave +vs id as parent id Commented Apr 24, 2016 at 23:25
  • What exactly is $number? Commented Apr 24, 2016 at 23:30
  • @null05 its the starting parentid of home page that is -1. That function didn't worked well. Commented Apr 24, 2016 at 23:42

2 Answers 2

1

What it should do is start by printing the ones with 0 as parent, for each one find it's children and start again for each children.

Something like:

function menu($data,$parent=-1) {
    $res='';    
    foreach($data as $e) {
        if($e['parent_id']==$parent||($parent==-1&&$e['parent_id']==0)) { //Also search for 0 when parent is  -1 as are both the roots
            $res.='<li>'.$e['url']; //Or whatever you want to show
            $sub=menu($data,$e['id']);
            if($sub) $res.='<ul>'.$sub.'</ul>';
            $res.='</li>';
         }
    }
    return $res;
}

<ul><?=menu($data)?></ul>
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a bunch. This works great. I'll use this but can you provide a way to return an array instead of printing it? I don't understand how to do that. But This works very nice for my situation.
Exactly as you did it. Populating an array instead of printing.
0

Thanks to Gabriel, I have used his method to create an other method that returns an array for the menu.

 $data = array(
    array('id'=>1, 'parent_id'=>-1, 'url_title'=>'home', 'url'=>'/home'),
    array('id'=>2, 'parent_id'=>0, 'url_title'=>'page-one', 'url'=>'/page-one'),
    array('id'=>3, 'parent_id'=>2, 'url_title'=>'sub-page', 'url'=>'/sub-page'),
    array('id'=>4, 'parent_id'=>3, 'url_title'=>'inner-page', 'url'=>'/inner-page')
    );


function menu_html($data,$parent=-1) {
    $res='';
    foreach($data as $e) {
        if($e['parent_id']==$parent||($parent==-1&&$e['parent_id']==0)) {
            $res.='<li>'.$e['url'];
            $sub=menu_html($data,$e['id']);
            if($sub) $res.='<ul>'.$sub.'</ul>';
            $res.='</li>';
         }
    }
    return $res;
}

echo '<ul>'.menu_html($data).'</ul>';

function menu_array($data,$parent=-1) {
    $res=array();
    foreach($data as $e) {
        if($e['parent_id']==$parent||($parent==-1&&$e['parent_id']==0)) {
            $res[$e['url']] = $e;
            $sub=menu_array($data, $e['id']);
            if($sub) $res[$e['url']]['sub-nav'] = $sub;
         }
    }
    return $res;
}

echo "<pre>";
print_r(menu_array($data));
echo "</pre>";

Output:

    /home
    /page-one
        /sub-page
            /inner-page

Array
(
    [/home] => Array
        (
            [id] => 1
            [parent_id] => -1
            [url_title] => home
            [url] => /home
        )

    [/page-one] => Array
        (
            [id] => 2
            [parent_id] => 0
            [url_title] => page-one
            [url] => /page-one
            [sub-nav] => Array
                (
                    [/sub-page] => Array
                        (
                            [id] => 3
                            [parent_id] => 2
                            [url_title] => sub-page
                            [url] => /sub-page
                            [sub-nav] => Array
                                (
                                    [inner-page] => Array
                                        (
                                            [id] => 4
                                            [parent_id] => 3
                                            [url_title] => inner-page
                                            [url] => inner-page
                                        )

                                )

                        )

                )

        )

)

Comments

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.