【问题标题】:Eloquent complex relationship for a chat message system in laravellaravel中聊天消息系统的雄辩复杂关系
【发布时间】:2021-02-05 23:23:47
【问题描述】:

我正在编写一个聊天系统,我有以下表格:

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') 但为了让它按我的预期工作,我需要传入一个用户 ID...理想情况下我只想能够从查询开始引用 Auth::user->id...但是如果我在 messages 方法上有一个参数,它将不会追加...

->whereHas('user', function ($query) use ($user_id) {
    $query->where('user_id', $user_id);
})

简而言之,我希望对话返回属于当前用户的所有消息,这些消息不会通过 chat_message_user 数据透视表为该特定用户删除。

【问题讨论】:

  • 我也在构建一个聊天系统,但我没有考虑只删除一些用户的消息。我会添加一个名为 hide_message_from_user 的新对象,其中包含一对多。然后您可以加载关系并将其设为关系为空的条件。

标签: php laravel eloquent


【解决方案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);
}]);

【讨论】:

  • 从技术上讲,我尝试了这种方法,但当时我无法让它发挥作用,很可能是因为其他因素,但是我重新审视了这种方法,基本上它是有效的。这种方法的问题是我不能在同一个查询中将用户消息“附加”到对话中,例如: User::find(1)->conversations() 应该按照您的定义返回带有各自 userMessages 的对话。现在,我需要单独查询 userMessages 集合并将其与我的对话集合合并。但是,我确实看到了将消息分开的好处......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-16
  • 2015-03-14
  • 2018-11-28
  • 2015-01-11
  • 2021-06-03
  • 2020-03-26
相关资源
最近更新 更多