Объединить JOIN с подзапросом:
$chats = Chat::select('chats.*')
->join('messages', 'messages.chat_id', 'chats.id')
->where('chats.direct_chat', 1)
->where('messages.id', function ($query) {
$query->select('id')
->from('messages')
->whereColumn('chat_id', 'chats.id')
->latest()
->limit(1);
})
->whereHas('users', function ($query) {
$query->where('id', '=', Auth::id());
})
->latest('messages.created_at')
->with(['messages.users', 'users' => function ($query) {
$query->where('id', '!=', Auth::id());
}])
->get();
Обратите внимание, что этот запрос выбирает только чаты с хотя бы одним сообщением.