Skip to content
Advertisement

Nested comment system runs too many queries ( laravel & livewire )

I’ve built a nested comment system and it works fine, but I have a problem. when I want to show the comments, it runs too many queries. for example if I have 10 comments and two replies each, laravel debugger shows 40+ queries, and I want to reduce them, here is my code :

Query

$comments = $post->mentions()->with(['author', 'reply'])->get();

Relationship in Post.php Model

public function mentions()
    {
        return $this->hasMany(Comment::class, 'post_id')->where('approved',1)->where('parent_id',0);
    }

Comments Relationships

 public function author()
    {
        return $this->belongsTo(User::class, 'author_id')->select('id', 'name', 'avatar', 'role');
    }

    public function reply()
    {
        return $this->hasMany(Comment::class, 'parent_id')->where('approved', 1);
    }

Blade File

@foreach ($comments as $comment)
    <div x-data="{reply:false}" class="break-words bg-white border-2 rounded-lg p-4 my-5" id="answer-{1}">
        <div wire:ignore class="flex justify-between items-center">
            <div class="flex items-center">
                <img class="rounded-full w-20 border-4 @if ($comment->author->role == 'administrator') border-blue-500 @else border-gray-500 @endif " src="{{ $comment->author->avatar }}"
                    alt="{{ $comment->author->name }}">
                <div>
                    <div class="flex pr-3">
                        <a href="/@username"
                            class="font-bold text-lg text-gray-800 hover:text-gray-900">{{ $comment->author->name }}</a>
                        @if ($comment->author->role == 'administrator')
                            <img class="w-5 mr-1" src="/img/verified.svg" alt="" title="admin">
                        @endif
                    </div>
                    <p class="font-light cursor-default text-gray-700 pt-1 pr-3">
                        {{ $comment->created_at->diffForHumans() }}</p>
                </div>
            </div>
            <svg @click="reply = true" xmlns="http://www.w3.org/2000/svg" class="h-6 cursor-pointer hover:text-rose-600"
                fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                    d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6" />
            </svg>
        </div>
        <div class="comment_body leading-8 pt-3 text-gray-800 cursor-default">
            <div wire:ignore>
                {!! nl2br($comment->body) !!}
            </div>
            <div x-cloak x-show="reply">
                <form class="py-3" wire:submit.prevent="SubmitComment({{ $comment->id }})">
                    <textarea wire:model.defer="commentBody"
                        class="w-full focus:ring-0 bg-zinc-200 border shadow focus:bg-zinc-100 mt-3 p-4 rounded-lg"
                        id="editor" rows="6" placeholder=""></textarea>
                    @error('commentBody') <p class="text-red-600 mt-1 text-sm">{{ $message }}</p>
                    @enderror
                    <div class="flex mt-3">
                        <div @click="reply = false"
                            class="bg-red-600 rounded-lg ml-3 text-white px-3 py-2 cursor-pointer">
                            Cancel
                        </div>
                        <button wire:loading.remove wire:target="SubmitComment" type="submit"
                            class="inline-block bg-gray-800 hover:bg-gray-900  transition duration-300 px-3 py-2  text-white rounded-md">
                            Send
                        </button>
                        <button wire:loading="" wire:target="SubmitComment" type="button"
                            class="flex bg-gray-800 hover:bg-gray-900  transition duration-300 px-3 py-2  text-white rounded-md"
                            disabled>
                            <span class="flex justify-center">
                                <svg class="animate-spin w-6 h-6" xmlns="http://www.w3.org/2000/svg" fill="none"
                                    viewBox="0 0 24 24">
                                    <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor"
                                        stroke-width="4"></circle>
                                    <path class="opacity-75" fill="currentColor"
                                        d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z">
                                    </path>
                                </svg>
                            </span>
                        </button>
                    </div>
                </form>
            </div>
            <div class="my-3">
                @include('partials.comment',['comments'=>$comment->reply])
            </div>
        </div>
    </div>
@endforeach

Advertisement

Answer

You can use dot seperator to get the nested relationship

$comments = $post->with(['mentions.author','mentions.reply'])
   ->first()
   ->mentions;
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement