Как переписать запрос на Eloquent?

У меня есть следующий запрос, который выводит мне нужный результат (список чатов пользователя и последнее сообщение в чате):

DB::table('chat_room_user')
    ->join('chat_rooms', 'chat_room_user.chat_room_id', 'chat_rooms.id')
    ->join('users', 'chat_room_user.user_id', 'users.id')
    ->join('messages', 'messages.chat_room_id', 'chat_rooms.id')
    ->select('chat_rooms.id', 'chat_rooms.title','messages.message AS last_message','messages.updated_at')
            ->where('users.id', $id)
            ->whereIn('messages.id', function ($query) {
                $query->select(DB::raw('MAX(messages.id)'))->from('messages')->groupBy('messages.chat_room_id');
            })
    ->orderBy('messages.created_at', 'desc')
    ->get();

Я получаю такой результат:

{
    "result": [
        {
            "id": 5,
            "title": "Chat 3",
            "last_message": "Hello",
            "updated_at": null
        },
        {
            "id": 1,
            "title": "test chat",
            "last_message": "Голосовое сообщение",
            "updated_at": "2022-07-27 15:50:03"
        }
    ]

}

Хотелось бы переписать запрос с использованием возможностей Eloquent, но у меня не получается. Создал модель: ChatRoom, User, Messages. Модели связал

User.php

public function chatRooms(): BelongsToMany
{
    return $this->belongsToMany(ChatRoom::class, 'chat_room_user')
        ->withTimestamps();
}

Message.php

public function chatRoom(): BelongsTo
{
    return $this->belongsTo(ChatRoom::class);
}

public function scopeLastInChat(Builder $query): Builder
{
    return $query->select('message AS last_message', 'updated_at')->whereIn('id', function 
        ($query) {
            $query->select(DB::raw('MAX(messages.id)'))->from('messages')->groupBy('messages.chat_room_id');
        })->orderBy('created_at', 'DESC');
    }

ChatRoom.php

public function messages(): HasMany
{
    return $this->hasMany(Message::class);
}

public function users(): BelongsToMany
{
    return $this->belongsToMany(User::class, 'chat_room_user');
}

Теперь в своем контроллере я получаю вроде все, что мне нужно:

public function chatRoomsByUser(int $id): JsonResponse
{
    $user = User::query()->find($id);
    $chatRooms = $user->chatRooms;
    $messages = Message::lastInChat()->get();

    return response()->json(['result' => $chatRooms->merge($messages)]);
}

Но я теперь получаю такой результат

{
    "result": [
        {
            "id": 1,
            "title": "test chat",
            "created_at": "2022-07-27T11:42:36.000000Z",
            "updated_at": "2022-07-27T11:42:36.000000Z",
            "pivot": {
                "user_id": 8,
                "chat_room_id": 1,
                "created_at": null,
                "updated_at": null
            }
        },
        {
            "id": 5,
            "title": "Chat 3",
            "created_at": "2022-08-01T08:54:04.000000Z",
            "updated_at": null,
            "pivot": {
                "user_id": 8,
                "chat_room_id": 5,
                "created_at": null,
                "updated_at": null
            }
        }
    ],
    "last_message": [
        {
            "last_message": "Hello",
            "updated_at": null
        },
        {
            "last_message": "Голосовое сообщение",
            "updated_at": "2022-07-27T12:50:03.000000Z"
        }
    ]
}

Как мне добится такого же рузльтат как в первом случае (с Db query) только при помощи Eloqent


Ответы (0 шт):