Красноречивые сложные отношения для системы сообщений чата в laravel

#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 отдельно и объединить ее с моей коллекцией разговоров. Тем не менее, я вижу преимущество в сохранении отдельных сообщений…