Search code examples
phplaraveleager-loading

how to eager loading nested relations and not repeat them at top level?


a have a comments table that has these fields: id, body, parent_id

each comment can have comments, that's why it has a parent_id column.

class Comment extends Model
{
    public function comments()
    {
        return $this->HasMany($this, 'parent_id');
    }
}

It can have child comments up to two levels only.

In my controller I retrieve the information this way:

return Comment::with('comments.comments')->get();

The resulting response is like this:

[
    {
        "id": 1,
        "body": "test",
        "parent_id": null,
        "comments": [
            {
                "id": 2,
                "body": "test",
                "parent_id": 1,
                "comments": [
                    {
                        "id": 3,
                        "body": "test",
                        "parent_id": 2
                    },
                    {
                        "id": 4,
                        "body": "test",
                        "parent_id": 2
                    }
                ]
            },
            {
                "id": 5,
                "body": "test",
                "parent_id": 1,
                "comments": []
            }
        ]
    },
    {
        "id": 2,
        "body": "test",
        "parent_id": 1,
        "comments": [
            {
                "id": 3,
                "body": "test",
                "parent_id": 2,
                "comments": []
            },
            {
                "id": 4,
                "body": "test",
                "parent_id": 2,
                "comments": []
            }
        ]
    },
    {
        "id": 3,
        "body": "test",
        "parent_id": 2,
        "comments": []
    },
    {
        "id": 4,
        "body": "test",
        "parent_id": 2,
        "comments": []
    },
    {
        "id": 5,
        "body": "test",
        "parent_id": 1,
        "comments": []
    },
    {
        "id": 6,
        "body": "test",
        "parent_id": null,
        "comments": []
    }    
]

What I would to retrive is this:

[
    {
        "id": 1,
        "body": "test",
        "parent_id": null,
        "comments": [
            {
                "id": 2,
                "body": "test",
                "parent_id": 1,
                "comments": [
                    {
                        "id": 3,
                        "body": "test",
                        "parent_id": 2
                    },
                    {
                        "id": 4,
                        "body": "test",
                        "parent_id": 2
                    }
                ]
            },
            {
                "id": 5,
                "body": "test",
                "parent_id": 1,
                "comments": []
            }
        ]
    },
    {
       "id": 6,
       "body": "test",
       "parent_id": null,
       "comments": []
    }       
]

I would like that the child comments don't repeat again at top level, what can I do? thank you.


Solution

  • Add whereNull(‘parent_id’) to your top level query.

    return Comment::whereNull('parent_id')->with('comments.comments')->get();