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

abdulaziz's avatar

latest()->first() not working

Hi! When I run this query :

User::
        with(['comments' => function ($query) {
            $query->latest();
        },'department'])
        ->whereHas('comments', function (Builder $query) {
            $query->where('from_id', auth()->user()->id)
                  ->orWhere('to_id', auth()->user()->id);
        })
        ->get();

I get an array of Users where the first User has 3 comments. But when add first() after latest() like so:

User::
        with(['comments' => function ($query) {
            $query->latest()->first();
        },'department'])
        ->whereHas('comments', function (Builder $query) {
            $query->where('from_id', auth()->user()->id)
                  ->orWhere('to_id', auth()->user()->id);
        })
        ->get();

First User has an empty array of comments. Also if I try to get only one User like so:

User::
        with(['comments' => function ($query) {
            $query->latest()->first();
        },'department'])
        ->whereHas('comments', function (Builder $query) {
            $query->where('from_id', auth()->user()->id)
                  ->orWhere('to_id', auth()->user()->id);
        })
        ->first();

Last comment is present. I dont understand such behaviour. What am I doing wrong? Please help

0 likes
15 replies
abdulaziz's avatar

Yes I did. The same thing empty array of comments

Snapey's avatar

Your comments are not just BY the user, some are FOR the user

Suppose the latest comment is not by the user? What does your 'comments' relationship look like in order to find comments by or for the user?

1 like
abdulaziz's avatar

I have a comments model that has One To Many Polymorphic relationship to models like Task, Product, Chat and User. This is what my Comment looks like:

create_comments_table.php

Schema::create('comments', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('user_id');
            $table->unsignedBigInteger('commentable_id');
            $table->string('commentable_type');
            $table->text('body');
            $table->timestamps();
        });

user_id is sender of comment

Comment.php

protected $fillable = ['user_id', 'body', 'commentable_id', 'commentable_type'];

protected $with = ['sender'];

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

public function sender()
{
        return $this->belongsTo('App\User','user_id');
}

Chat.php

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

User.php

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

As you can see Chat and User have comments. So what I am trying to do is:

Get list of Users that I have sent or received messages from with last message attached to the result (doesn't matter sent by him or me) so that I can sort Users by last message date later on

$messagedUsers = User::
        with(['comments' => function ($query) {
            $query->latest()->take(1); // last message doesnt matter whose 
        }])
        ->whereHas('comments', function (Builder $query) {
            $query->where('user_id', auth()->user()->id) // sent by me
                  ->orWhere('commentable_id', auth()->user()->id); // sent to me
        })
        ->get();
munazzil's avatar

End of the query use as like below with get(),

   ->get()->toArray();
munazzil's avatar

Remove the auth()->user()->id and check with only auth()->user() because however you try the result will be one when it comes to auth()->user().

abdulaziz's avatar

auth()->user() return User himself with all fields but I need only ID to compare. Thats why auth()->user() wont work

conclusivetech's avatar

auth()->user() return User himself with all fields but I need only ID to compare. Thats why auth()->user() wont work

auth()->user()->id?

abdulaziz's avatar

Figured out something: In my result I am getting all User that I have chated with but only one of those Users has last comment attached it. So maybe latest()->first() is working after all but not the way it suppose to?

munazzil's avatar

try with like below then,

   User::
    with(['comments' => function ($query) {
        $query->first();
    },'department'])
    ->whereHas('comments', function (Builder $query) {
        $query->where('from_id', auth()->user()->id)
              ->orWhere('to_id', auth()->user()->id);
    })
    ->latest()->get();

else use oldest() instead of latest()

abdulaziz's avatar

auth()->user()->id?

Yes I have this code right now. He wanted me to change it to auth()->user()

Snapey's avatar
Snapey
Best Answer
Level 122

You will learn to ignore @munazzil

I see you totally changed the query?

You should be able to create a new relationship on the user model for latest comment which is a hasOne type.

Test this on its own first

2 likes
abdulaziz's avatar

Came up with this. Thanks to all. You are the best!

User.php

    public function latestComment()
    {
        return $this->hasOne('App\Comment','commentable_id')
                    ->where('commentable_type','App\User')
                    ->latest();
    }

Controller

        $messagedUsers = User::whereHas('latestComment',function(Builder $query){
            $query->where('commentable_id', auth()->user()->id)
                  ->orWhere('user_id', auth()->user()->id); 
        })->with('latestComment')
        ->get();
abdulaziz's avatar

Oops this code only returns Auth user's message as a last message. But need as a last message: sent by auth or sent to auth ( Trying to fix

Please or to participate in this conversation.