laravelcontrollerforum

Laravel display latest comment of a post


I have a table of threads, and on the index page I want to display the latest comment of the thread. So far I have selected the latest comment and try to display it on the page, but it only displays the latest comment overall, not the latest for the specific postenter image description here

So my ThreadsController looks like this right now, selecting all the comments and displaying the latest one first.

 public function index()
    {
        $threads = Thread::latest()->paginate(10);
        $latestComment = Comment::latest()->first();
        return view('threads.index', compact('threads', 'latestComment'));
    }

Thread model

public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }

Comment Model

public function user() {
        return $this->belongsTo(User::class);
    }

    public function thread()
    {
        return $this->belongsTo(Thread::class);
    }

    public function commentable() {
        return $this->morphTo();
    }

So how do I select the latest comment from the specific thread and display it on the index?

Edit:

Controller:

public function index()
    {
        $threads = Thread::latest()->with('comments')->paginate(10);

        return view('threads.index', compact('threads'));
    }

Index blade:

@foreach($threads as $thread)
    {{ $thread->latestComment->user->name }}
@endforeach

Comments table migration

 public function up()
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('user_id');
            $table->string('body');

            $table->unsignedBigInteger('commentable_id');
            $table->string('commentable_type');
            $table->timestamps();
        });
    }

Solution

  • You have defined your relationship between a Thread and Comment correctly, but you're not making use of that relationship in the index function of your ThreadsController. You're just grabbing the latest 10 Threads and the most recent Comment, but not the comment related to your Thread.

    What you're wanting is to get all your Threads and pass them to your view with their latest Comment.

    You can use eager loading to attach your Comment relationships to your models.

    Thread::latest()->with('comments')->paginate(10);
    

    That will grab your 10 latest Threads along with their Comments. So in your view you could do something like:

    @foreach ($threads as $thread)
        {{ $thread->comments()->latest('id')->first()->comment }}
    @endforeach
    

    Whilst this works, it's a bit verbose. So what you can do is piggy back off your comments function to return just the most recent Comment as a relationship.

    class Thread extends Model
    {
        use HasFactory;
    
        public function comments()
        {
            return $this->morphMany(Comment::class, 'commentable');
        }
    
        public function latestComment()
        {
            return $this->morphOne(Comment::class, 'commentable')->latest('id');
        }
    }
    

    This gives you shorter method for accessing the latest Comment for a Thread.

    So going back to your scenario;

    In your ThreadsController.php

    public function index()
    {
      $threads = Thread::latest()->with('latestComment')->paginate(10);
      return view('threads.index', compact('threads'));
    }
    

    Then in your index.blade.php file

    @foreach ($threads as $thread)
      {{-- Access whatever properties you have on your comment --}}
      {{ $thread->latestComment->id }} 
    @endforeach