0
votes

I have a collction of posts I´l like to show in a table. Each post has an id and a parent_id.

I want to loop through the table with a nested foreach, but I dont get it to work. My idea is to loop through each post, print the name and stuff, and also find all it´s children (by looping through each post and see if the childs parent id is equal to my id.)

My code is:

$allPosts = $posts;
foreach ($posts as $post) {
    if ($post->parent_id == 0){ //0 means highest level, no parent
        echo $post->name;
        $current_id = $post->id;

        foreach ($allPosts as $childPost){
            if($childPost->parent_id == $current_id){
                echo $cihldPost->name;

            }   
        }
    }
}

The problem is, the first loop does only run once. If I delete the second foreach-loop, the first one runs correctly.

Why is this happening, and how do I solve it?

ADDED: The post itself is like a blog post, it contains the following: id, title, body, compact, parent_id. Where id is the unique id, title and body as title and body to the blog post, compact as a short name used for the url, an the parent id to tell who the post is lying under, ie. Im a child to my parent.

Since the user should have all the possibility to move around the posts and put the posts in a menu, think of the top level posts as menu items, and the once that have a parent as the submenu item.

3
what does $childPost, $allPosts contain? what is the relation? - Shiplu Mokaddim
$allPosts = $posts, just to make the variables different even though it is the same posts. the childpost (which doesn´t have to be a childpost unless its parent_id==current_id), is just the name of the post i get in the for each. Each post contains name, id, parent_id, content, url, and other minor stuff. Think of it like a blog post. Does this makes sense? - Malin
@Malin if you post some sample content of $posts;, it will become easy for us to understand your problem - Sunil Kumar

3 Answers

2
votes

My idea is to loop through each post, print the name and stuff, and also find all it´s children (by looping through each post and see if the childs parent id is equal to my id.)

Currently, you're just trying to loop through the same object once again. The $allPosts variable isn't necessary. If you're trying to loop through each child element, then you need to use $post inside the nested foreach loop.

You're currently doing:

$obj2 = $obj;
foreach ($obj as $child) {
    foreach ($obj2 as $anotherchild) {
    # code...
    }
}

Roughly, the structure should look like:

foreach ($obj as $child) {
    foreach ($child as $secondchild) {
      # code...
    }
}

With your code:

foreach ($posts as $post) {
    if ($post->parent_id == 0){ //0 means highest level, no parent
        echo $post->name;
        $current_id = $post->id;

        foreach ($post as $childPost){
            if($childPost->parent_id == $current_id){
                echo $cihldPost->name; // <-- typo?    
            }   
        }
    }
}
0
votes

for some reason, the foreach did not work on the $posts object itself that my Controller was passing on to my view. However, if I saved the $posts in a local array, it all worked. I still dont know why I had the problem in the first place, so please comment or provide a better answer that this.

    $mylist = array();
foreach($posts as $post) {
    $listitem = array();
    $listitem['id'] = $post->id;
    $listitem['parent_id'] = $post->parent_id;
    $listitem['title'] = $post->title;
    $listitem['compact'] = $post->compact;
    $mylist[] = $listitem;
}
foreach($mylist as $listitem){
    #code..
    foreach($mylist as $inneritem){
         #code..
    }
}
0
votes

Here is how I changed your code:

$posts = array(
    (object) array("parent_id" => 0, "id" =>  1, "name" => 'Outer 1'),
    (object) array("parent_id" => 0, "id" =>  2, "name" => 'Outer 2'),
    (object) array("parent_id" => 0, "id" =>  3, "name" => 'Outer 3'),
    (object) array("parent_id" => 0, "id" =>  4, "name" => 'Outer 4'),
    (object) array("parent_id" => 0, "id" =>  5, "name" => 'Outer 5'),
    (object) array("parent_id" => 1, "id" =>  6, "name" => 'Inner 1.1'),
    (object) array("parent_id" => 1, "id" =>  7, "name" => 'Inner 1.2'),
    (object) array("parent_id" => 4, "id" =>  8, "name" => 'Inner 4.1'),
    (object) array("parent_id" => 5, "id" =>  9, "name" => 'Inner 5.2'),
    (object) array("parent_id" => 5, "id" => 10, "name" => 'Inner 5.2'),
    (object) array("parent_id" => 5, "id" => 11, "name" => 'Inner 5.3'),

);

$allPosts = $posts;
foreach ($posts as $post) {
    if ($post->parent_id == 0){ //0 means highest level, no parent
        echo $post->name . ' : ';
        $current_id = $post->id;

        foreach ($allPosts as $childPost){
            if($childPost->parent_id == $current_id){
                echo $childPost->name . ', ';
            }
        }
        echo '<br>';
    }
}

Outputs the following:

Outer 1 : Inner 1.1, Inner 1.2, 
Outer 2 : 
Outer 3 : 
Outer 4 : Inner 4.1, 
Outer 5 : Inner 5.2, Inner 5.2, Inner 5.3, 

If the problem is not in your code (which looks okay to me, and also works as expected on my computer) it may be in the structure of the $posts array. Try and use var_dump on the variables to see if they contain incomplete or incorrect data.