【问题标题】:List conversation between 2 users in the correct order按正确顺序列出 2 个用户之间的对话
【发布时间】:2018-04-04 04:37:53
【问题描述】:

我想创建一个聊天系统,我可以在上面列出特定 2 个人之间的所有聊天

我有两张桌子userschats

我的聊天表有 3 列 - user_idfriend_idchat

我的User.php模型文件是这样的

public function chats() {
    return $this->hasMany('App\Chat');
}

例如:

我想在不改变对话顺序的情况下列出用户 1 和 3 之间的所有聊天
我可以通过 $chats = Auth::user()->chats->where('friend_id', '=', $id); 简单地做到这一点,但这只会给经过身份验证的(即用户 1 或 3)用户聊天。但我想要他们两个之间的对话。
所以我找到了另一种方法来做到这一点

$first = Chat::all()->where('user_id', '=', Auth::user()->id)->where('friend_id', '=', $id);
$second = Chat::all()->where('user_id', '=', $id)->where('friend_id', '=', Auth::user()->id);
$chats = $first->merge($second);

但是这种方式有一些问题。这不会以正确的顺序进行聊天。我认为不可能正确订购。

所以我的问题是如何以正确的顺序轻松列出两个人之间的对话?
如果您想了解有关我的问题的更多详细信息,可以询问。

【问题讨论】:

  • 您的表中没有排序机制。在默认情况下,关系数据中的顺序不能保证,因为它应该无关紧要。如果您希望顺序很重要,那么您需要添加一列来指示顺序(例如日期时间?)。
  • @apokryfos 我理解你。但是有没有其他方法可以通过使用 laravel eloquent 或其他比包更简单的方法来做到这一点?

标签: php laravel vue.js eloquent


【解决方案1】:

您应该能够通过参数分组在一个查询中完成此操作,而不是执行两个单独的查询然后合并它们。

Chat::where(function ($query) use ($id) {
    $query->where('user_id', '=', Auth::user()->id)
          ->where('friend_id', '=', $id);
})->orWhere(function ($query) use ($id) {
    $query->where('user_id', '=', $id)
          ->where('friend_id', '=', Auth::user()->id);
})->get();

可能也会以正确的顺序返回您的结果,只是因为没有指定任何排序标准,数据库通常会按照插入的顺序返回行。但是,如果不在您的聊天表中添加一些内容以进行排序(时间戳或自动增量 ID),则无法保证。

【讨论】:

    【解决方案2】:

    这样试试

    $first = Chat::all()->where('user_id', '=', Auth::user()->id)
             ->where('friend_id', '=', $id)->get();
    $second = Chat::all()->where('user_id', '=', $id)
              ->where('friend_id', '=', Auth::user()
              ->id)->get();
    $chats = $first->merge($second)
             ->sortBy('created_at');//created_at is timing added change if other
    

    【讨论】:

    • 谢谢。但是对于这种聊天应用程序是否有任何 laravel 推荐的方法,或者有没有其他方法可以通过使用 Laravel eloquent 来做到这一点?
    • 您可以将所有聊天消息存储在一个表中以方便使用。
    • @user2486 指出,created_at 正是“Laravel 方式”,如果你关心的话。只需配置您的模型(laravel.com/docs/5.5/eloquent#defining-models
    【解决方案3】:

    首先,你不应该在过滤之前做all()。这很糟糕,因为会获取所有表数据,然后在 PHP 中进行过滤。

    你应该考虑这样做:

    在您的迁移中:

    Schema::create("chat", function (Blueprint $table) {
        //Other creation lines
        $table->timestamps();
    })
    

    然后在你的聊天模型中:

    public function scopeInvolvingUsers($query, $userId,$friendId) {
         return $query->where([ ["user_id",$userId],["friend_id",$friendId] ])
                      ->orWhere([ ["user_id",$friendId],["friend_id",$userId] ]);
    } 
    

    然后您可以执行以下操作:

    $chats = Chat::involvingUsers(\Auth::id(),$otherId)->latest()->get();
    

    注意latestearliest 要求timestamps 出现在桌子上。

    【讨论】:

      【解决方案4】:

      我将在聊天表中添加时间戳以确保顺序。 要将时间戳添加到聊天表中,只需添加

      $table->timestamps();
      

      您可以选择与用户相关的聊天并按created_at排序。 在 laravel 5.3+ 中使用

      Chats::where(['user_id', '=', Auth::id()], ['friend_id', '=', $id])->orWhere(['user_id', '=', $id], ['friend_id', '=', Auth::id()])->sortBy('created_at');
      

      【讨论】:

        【解决方案5】:
        Chat::whereIn('user_id', [$id, Auth->user()->id])
        ->whereIn('friend_id', [$id, Auth->user()->id])->get();
        

        【讨论】:

          猜你喜欢
          • 2016-06-11
          • 1970-01-01
          • 1970-01-01
          • 2018-11-24
          • 1970-01-01
          • 2016-03-01
          • 2019-02-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多