获取“像信使一样”的聊天列表

Posted

技术标签:

【中文标题】获取“像信使一样”的聊天列表【英文标题】:Get a list of chats "like a messanger" 【发布时间】:2019-12-29 01:37:11 【问题描述】:

我的代码有问题。我想获得独特的用户/对话。 我的数据库是这样的

ID| FROM | TO | MESSAGE 

我想获得此聊天的唯一列表,但是当我有 (1,2) (2,1) 有人回答时,我的记录增加了一倍。

Message::select('from','to','message','created_at')->latest()->where('from',Auth::id())->orWhere('to',Auth::id())->with('from','to')->distinct('from','to')->get()

【问题讨论】:

distinct('from','to') 应该做什么? distinct() 方法没有任何参数。 如果用户发送多条消息,我将全部接收。我只想要一个最新的。 如果 1 向 2 (1,2) 发送消息,2 向 1(2,1) 发送消息,也可以有多个消息。您想将其视为一对 (1,2) 并且只想要最新消息? 我想要一对没有双对的。所以我可以用它渲染聊天。最新消息。 我可以用 js 做到这一点,但我希望这是清晰和最佳的...... 【参考方案1】:

您实际上似乎想要的是您当前经过身份验证的用户之前与之进行过对话的用户列表。您可以通过以下查询获取此用户:

use Illuminate\Database\Eloquent\Builder;

$authId = auth()->id();

$users = User::query()
    ->whereHas('messages', function (Builder $query) use ($authId) 
        $query->where('from', $authId)
            ->orWhere('to', $authId);
    )
    ->get();

然后,您可能希望显示每个用户的对话预览,最有可能的是您所描述的最新消息。检索此消息可能会很棘手,但在子查询和特殊关系的帮助下,它非常简单。

首先,我们需要扩展我们的用户查询以包含最新消息的 id:

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\Builder as QueryBuilder;

$authId = auth()->id();

$users = User::query()
    ->whereHas('messages', function (Builder $query) use ($authId) 
        $query->where('from', $authId)
            ->orWhere('to', $authId);
    )
    ->where('id', '!=', $authId)
    ->select()
    ->selectSub(function (QueryBuilder $query) use ($authId) 
        $query->from('messages')
            ->where(function (QueryBuilder $query) use ($authId) 
                $query->whereColumn('messages.from', 'users.id')
                    ->where('messages.to', $authId);
            )
            ->orWhere(function (QueryBuilder $query) use ($authId) 
                $query->whereColumn('messages.to', 'users.id')
                    ->where('messages.from', $authId);
            )
            ->orderByDesc('created_at')
            ->limit(1)
            ->select('id');
    , 'last_message_id')
    ->get();

然后,我们只需为用户模型上的最新消息定义一个HasOne 关系:

use Illuminate\Database\Eloquent\Relations\HasOne;

class User extends Authenticatable

    public function lastMessage(): HasOne
    
        return $this->hasOne(Message::class, 'id', 'last_message_id');
    

现在,我们所要做的就是将->with('lastMessage') 添加到我们的查询中,我们将能够使用来自或发往我们当前已验证用户的最后一条消息来迭代我们的用户。

【讨论】:

我认为我做错了,当我收到消息时 (1,2) (2,1) User_1 => User_2 和 User_2 => User_1 这个查询给了我 User_2 和我 User_1 当我添加 @if($message->id !==auth()->id) Chat_here @endif 一切正常。但我不想那样做。 您确定您的测试数据包含正确的 ID?最后一个 if 显然是错误的。想想吧。 现在我有 (1,2) (2,1) 和 (1,3)。用户中的消息关系如下所示: return $this->hasMany('App\Message','to','id');但我的问题仍然存在 我更新了查询,last_message_id 缺少一些基本的where 部分。对不起。【参考方案2】:

在这一刻,我想像这样。而这项工作。如果有人有更好的解决方案。

 $authId = auth()->id();

    $users =
        User::query()->whereHas('messages_from', function (Builder $query) use ($authId) 
            $query->where('from', $authId)
                ->orWhere('to', $authId);
        )->where('id', '!=', $authId)
        ->orwhereHas('messages_to', function (Builder $query) use ($authId) 
        $query->where('from', $authId)
            ->orWhere('to', $authId);
    )
        ->where('id', '!=', $authId)
        ->select()
        ->selectSub(function (QueryBuilder $query) use ($authId) 
            $query->from('messages')
                ->where(function (QueryBuilder $query) use ($authId) 
                    $query->whereColumn('messages.from', 'users.id')
                        ->where('messages.to', $authId);
                )
                ->orWhere(function (QueryBuilder $query) use ($authId) 
                    $query->whereColumn('messages.to', 'users.id')
                        ->where('messages.from', $authId);
                )
                ->orderByDesc('created_at')
                ->limit(1)
                ->select('message');
        , 'message')
        ->get();
    return $users->jsonSerialize();

用户.php

     public function messages_from()
            return $this->hasMany('App\Message','from','id');
        
        public function messages_to()
            return $this->hasMany('App\Message','to','id');
        

【讨论】:

以上是关于获取“像信使一样”的聊天列表的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能使用 RijndaelManaged 解密数据?

如何使用信使聊天机器人访问某人的姓名? (Facebook 信使 SDK)

我可以开发 IP 信使(局域网连接的计算机用户之间的消息传递/聊天)[关闭]

不要在加载时打开对讲信使

我如何为我的网站用户(如 Y!)制作实时客户端聊天应用程序!信使?

F11 workerman 聊天列表初始化之数据获取长连接下实现聊天列表实时更新完结