Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Formatink's avatar

Nested comments with eager loading

Hello,

I am currently doing a nested comments system.
In my model, I use this method to retrieve children of the comment

public function children()
{
     return $this->hasMany('App\Models\NewsComment', 'parent_id', 'id');
}

I get my comments like this :

$comments = NewsComment::with('children')
    ->where('parent_id', 0)
    ->where('news_id', $newsId)
    ->get();

and I display my comments like this :

@foreach($comments as $comment)
    @include('pages.news_comment', ['comment' => $comment])
@endforeach

Here is my pages.news_comment.blade.php file

{{ $comment->content }} <br/>

@if ($comment->children->count() > 0)
    @foreach ($comment->children as $comment)
        <div style="margin-left: 30px">
            @include('pages.news_comment', ['comment' => $comment])
        </div>
    @endforeach
@endif

The problem is that it makes a query to get children of each child.
The eager loading works only for the first children.

How could I get all children in advance and avoid this problem ?
Thank you in advance.

Regards,
Formatink

0 likes
5 replies
pmall's avatar

The only solution here is to query the whole list of comment related to this news, get it as an array, and have some method to construct the three.

Formatink's avatar

@pmall

get it as an array

Use the collection with models is not possible ? :/

pmall's avatar
pmall
Best Answer
Level 56

You can use the collection it doesnt mater.

The thing is you cant do recursive eager loading. You have to get all the articles comments in one query then construct the nested array/collection and display it.

Formatink's avatar

@pmall Ok, here is my solution, it works :)

    public function all($newsId)
    {
        $comments = NewsComment::where('news_id', $newsId)->get();
        $comments_by_id = new Collection;

        foreach ($comments as $comment)
        {
            $comments_by_id->put($comment->id, $comment);
        }

        foreach ($comments as $key => $comment)
        {
            $comments_by_id->get($comment->id)->children = new Collection;

            if ($comment->parent_id != 0)
            {
                $comments_by_id->get($comment->parent_id)->children->push($comment);
                unset($comments[$key]);
            }
        }

        return $comments;
    }
2 likes
ziayamin's avatar

@formatink i have this error "Trying to get property 'children' of non-object", in this section "$comments_by_id->get($comment->post_id)->children->push($comment);" please helep

Please or to participate in this conversation.