1

More specifically, I'm looking to pass a parent ID to the children, more over, if the children have grandchildren, I'd need to pass the ID of the child to the grandchildren... and so on and so forth for an unlimited number of nested items (hence the use of a recursive function).

Note: The post looks long, but it's mostly just output data! I'm pretty sure there is a simple solution to this but I can't figure it out after hours upon hours of attempts.

So far I have this:

<?php
session_start();
$data = '[{"id":13,"content":"This is some content"},{"id":14,"content":"This is some content"},{"id":15,"content":"This is some content","children":[{"id":16,"content":"This is some content"},{"id":17,"content":"This is some content"},{"id":18,"content":"This is some content","children":[{"id":19,"content":"This is some content","children":[{"id":20,"content":"This is some content","children":[{"id":21,"content":"This is some content"},{"id":22,"content":"This is some content"},{"id":23,"content":"This is some content"}]}]}]}]},{"id":24,"content":"This is some content"},{"id":25,"content":"This is some content"}]';
$menu = json_decode($data, true); 
$depth = 0;


function getData($array, $key, $depth) {

    if (!is_array($array)) {
        $depth = $depth/2;
        $depthHolder = $depth;

        if ($key == "id") {
            //I thought maybe I could write something in here to this effect, but was unsuccessful :(   
        }

        while ($depth != 1) {
            echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";            
            $depth--;
        }


        echo $depthHolder . ' - ' . $key . ' : ' . $array . '<br/> ';

    } else {
        $depth++;   
    }


    foreach($array as $key => $v) { 
        getData($v, $key, $depth);
    }


}

getData($menu, '', $depth);
?>

Which outputs this (currently the numbers in front just show the depth of the nested items):

1 - id : 13
1 - content : This is some content
1 - id : 14
1 - content : This is some content
1 - id : 15
1 - content : This is some content
        2 - id : 16
        2 - content : This is some content
        2 - id : 17
        2 - content : This is some content
        2 - id : 18
        2 - content : This is some content
                3 - id : 19
                3 - content : This is some content
                        4 - id : 20
                        4 - content : This is some content
                                5 - id : 21
                                5 - content : This is some content
                                5 - id : 22
                                5 - content : This is some content
                                5 - id : 23
                                5 - content : This is some content
1 - id : 24
1 - content : This is some content
1 - id : 25
1 - content : This is some content

I tried to use sessions but I still couldn't figure it out. What I'm looking for is shown in the example output below. You'll notice that the ID's in front of the rows have changed to show the previous parents ID and holds it until the next nested item shows up (0 represents 'no parent').

0 - id : 13
0 - content : This is some content
0  - id : 14
0 - content : This is some content
0 - id : 15
0 - content : This is some content
        15 - id : 16
        15 - content : This is some content
        15 - id : 17
        15 - content : This is some content
        15 - id : 18
        15 - content : This is some content
                18 - id : 19
                18 - content : This is some content
                        19 - id : 20
                        19 - content : This is some content
                                20 - id : 21
                                20 - content : This is some content
                                20 - id : 22
                                20 - content : This is some content
                                20 - id : 23
                                20 - content : This is some content
0 - id : 24
0 - content : This is some content
0 - id : 25
0 - content : This is some content

Sorry about the lengthy post! Thanks for reading, hopefully one of you geniuses can help me out. I will be grateful as I've tried for 6 hours to figure this one little issue out.

4
  • How do you know what element is a child of what element? Not seeing anything that would indicate that in the JSON string... Commented Mar 18, 2014 at 13:40
  • I was hoping to achieve this knowledge just based on the structure of the menu, but perhaps this isn't possible? Commented Mar 18, 2014 at 13:42
  • You'd need to at least identify what is a subsection of what for that. Is that what you're actually trying to do, build a menu with unlimited subsections? Commented Mar 18, 2014 at 13:49
  • Yes. Essentially allowing for as many sub-menus as possible. This is the menu builder - jsfiddle.net/Av8q5 Commented Mar 18, 2014 at 13:50

4 Answers 4

1

Perhaps this approach would be clearer:

function getData($parentkey,$array,$depth) {
  foreach ($array as $v) {
    print "$depth $parentkey id: {$v['id']}<br>$depth $parentkey content:{$v['content']}<br>";
    if (isset($v['children']))
      getData($v['id'],$v['children'],$depth."&nbsp;&nbsp;");
  }
}
getData(0,$menu,'');
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for lending a hand, this works perfectly. +1 & Accepted.
1

If you're trying to build a menu this way, you'll need to modify the data structures that you're returning. For example...

class item {
    public $id;
    public $content;
    public $subsections;
}

Then you can simply create them as nested, unordered lists by checking whether they have any subsections in your parsing functions.

function parse_items($items) {
    $html = '<ul>';

    foreach ($items as &$item) {
        $html .= '<li>' . $item->content . '</li>';

        if (count($item->subsections) > 0) {
            $html .= parse_items($item->subsections);
        }
    }

    $html .= '</ul>'
    return $html;
}

echo parse_items($items);

After this, you can just style how the menu will appear using CSS based on the depth of the <ul> element. Technically I know this is "cheating" because I added an array of elements to next the whole data structure, but if you have control over how the elements are returned, why not make it easier on yourself?

1 Comment

Thanks for you support! Appreciated greatly!
1

You can add the parent ID with this code:

function getData($arr, $parent=null) {
    if (is_array($arr)) {
        if (!isset($arr['id'])) {
            foreach ($arr as $key => $item) {
                $arr[$key] = getData($item, $parent);
            }
        } else {
            $id = $arr['id'];
            if ($parent) {
                $arr['parent'] = $parent;
            }
            if (isset($arr['children'])) {
                $arr['children'] = getData($arr['children'], $id);
            }
        }

    }
    return $arr;
}



print_r(getData($menu)); 

Maybe this helps you to move forward.

1 Comment

Thanks for you support! Appreciated greatly!
1

One way to do this:

function print_menu($menu, $key, $depth) {
    $indent_string = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
    foreach ($menu as $value) {
        $this_key = $value['id'];
        echo str_repeat ($indent_string, $depth).$key." - id : ".$value['id']."</br>";
        echo str_repeat ($indent_string, $depth).$key." - content : ".$value['content']."</br>";
        if (is_array($value['children'])) {
            print_menu ($value['children'],$this_key,$depth+1);
        }
    }
}

print_menu ($menu, 0, 0);

If you want to generate the HTML for the menu you could use:

function print_menu_1 ($menu, $key, $depth) {
    $indent_string = "    ";
    echo str_repeat($indent_string,$depth).'<ol class="dd-list">'."\n";
    foreach ($menu as $value) {
        $this_key = $value['id'];
        echo str_repeat($indent_string,$depth+1).'<li class="dd-item" data-id="'.$value['id'].'">'."\n";
        echo str_repeat($indent_string,$depth+2).'<div class="dd-handle">'.$value['content'].' for id #'.$value['id'].'</div>'."\n";
        if (is_array($value['children'])) {
           print_menu_1 ($value['children'],$this_key,$depth+1);
        }
        echo str_repeat($indent_string,$depth+1).'</li>'."\n";
    }
    echo str_repeat($indent_string,$depth).'</ol>'."\n";
}

print_menu_1 ($menu, 0, 0);

Please note that in this case the newlines and $indent_string are useful only to make the HTML code look good.

1 Comment

Thanks for you support! Appreciated greatly!

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.