#php #laravel #eloquent
#php #laravel #eloquent
Вопрос:
Я пишу систему чата, и у меня есть следующие таблицы:
chat_conversations: id, name
chat_messages: id, chat_conversation_id, message, deleted_at
chat_message_user: id, chat_message_id, user_id, is_sender, seen, deleted_at
chat_conversation_user: id, user_id, chat_conversation_id, is_owner
Я хочу, чтобы сообщения были связаны с пользователями отдельно, следовательно chat_message_user
, так, чтобы каждое сообщение можно было удалять по отдельности, но оставалось видимым для других пользователей в чате. Например, если я общаюсь с кем-то еще, и я хочу «удалить» разговор только со своей стороны, я хочу, чтобы у другого человека все еще была эта история чата на их стороне.
Я хочу иметь возможность запрашивать разговоры, принадлежащие auth::user, и добавлять сообщения, которые могут видеть только ОНИ (те, в которых chat_message_user НЕ удален)
Auth::user()->conversations
User
Модель:
...
public function conversations()
{
return $this->belongsToMany(ChatConversation::class)
->withTimestamps();
}
...
ChatConversation
Модель:
protected $appends = ['messages'];
public function messages()
{
return $this
->hasMany(ChatMessage::class)
->whereHas('user') //I want whereHas('user') to reference only the user id from the Auth::user()
->get();
}
public function getMessagesAttribute()
{
return $this->messages();
}
...
В настоящее время я пытаюсь использовать whereHas(‘user’) в моем методе сообщений, но для того, чтобы он работал так, как я задумал, мне нужно передать идентификатор пользователя… В идеале я просто хочу иметь возможность ссылаться на Auth::user-> id с начала запроса… Но если у меня есть параметр в методе messages, он не будет добавлен…
->whereHas('user', function ($query) use ($user_id) {
$query->where('user_id', $user_id);
})
В ореховой скорлупе я хочу, чтобы диалог возвращал все сообщения, принадлежащие текущему пользователю, которые не были удалены для этого конкретного пользователя через сводную таблицу chat_message_user.
Комментарии:
1. Я также создаю систему чата, но я не рассматривал возможность удаления сообщений только для некоторых пользователей. Я бы добавил новый объект с именем hide_message_from_user с соотношением один ко многим. Затем вы можете загрузить отношения и сделать это условием, при котором отношение равно нулю.
Ответ №1:
Я бы создал отношения в разговоре, чтобы запрашивать сообщения только для аутентифицированного пользователя.
В ChatConversation
public function userMessages()
{
return $this
->hasMany(ChatMessage::class)
->whereHas('user', function ($query) {
$query->where('user_id', Auth::id());
});
}
Обратите внимание, что без вызова ->get()
это фактическое отношение laravel, а не коллекция. Теперь вы можете легко запрашивать свои сообщения, как только у вас есть $conversation
объект:
$conversation->userMessages; // Collection of all the messages for the user in the conversation
$conversation->userMessages()->limit(10)->get(); // Only query 10 messages
Вы также можете загружать сообщения вместе с разговорами, используя eager loading:
User::find(1)->conversations()->with(['userMessages' => function ($query) {
$query->orderBy('created_at', 'DESC')->limit(10);
}]);
Комментарии:
1. Технически я пробовал этот метод, но в то время я не смог заставить его работать, скорее всего, из-за других факторов, однако я пересмотрел этот метод, и, по сути, он работает. Проблема с этим методом заключается в том, что я не могу «добавить» пользовательские сообщения в беседу в том же запросе, например: User::find(1)-> conversations() должен возвращать беседы с их соответствующими пользовательскими сообщениями, как вы определили. Теперь мне нужно запросить коллекцию userMessages отдельно и объединить ее с моей коллекцией разговоров. Тем не менее, я вижу преимущество в сохранении отдельных сообщений…