【问题标题】:Laravel count unread messagesLaravel 统计未读消息
【发布时间】:2021-07-21 08:46:00
【问题描述】:

我有 5 张桌子:

经理(ID、姓名) - 商店经理

对话框 (id) - 存储对话框

消息(id、dialog_id、文本) - 将消息存储在对话框中

dialog_manager (dialog_id, manager_id) - 链接到此对话框的商店经理

messages_read (message_id, manager_id, read_at) - 在每个经理阅读每条消息时存储信息。

我的 Dialog 类有一个关系:

public function messages() {
    return $this->hasMany(Message::class);
}

Manager 类也有关系:

public function dialogs() {
    return $this->belongsToMany(Dialog::class);
}

现在我想获取所选经理的每个对话框的未读消息数,如下所示:

$manager->dialogs()->withCount(['unread_messages']);

我为此编写了函数:

public function unread_messages() {
   $managerId = 1285; // For example
   return $this->messages()->leftJoin('messages_read', function ($join) use ($managerId) {
        $join->on('messages.id', '=', 'message_id')->on('messages_read.manager_id', '=', DB::raw($managerId));
   })->whereNull('messages_read.read_at');
}

但它不起作用 - 看起来“左连接”只是被忽略了,因为:

dd($manager->dialogs()->withCount(['unread_messages'])->get());

给出错误:

message: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'messages_read.read_at' in 'where clause' (SQL: select `dialogs`.*, (select count(*) from `messages` where `dialogs`.`id` = `messages`.`dialog_id` and `messages_read`.`read_at` is null) as `unread_messages_count`, `dialog_manager`.`manager_id` as `pivot_manager_id`, `dialog_manager`.`dialog_id` as `pivot_dialog_id` from `dialogs` inner join `dialog_manager` on `dialogs`.`id` = `dialog_manager`.`dialog_id` where `dialog_manager`.`manager_id` = 1285)

解决我的问题的最佳方法是什么?

UPD:添加了有关 manager 表的信息。

谢谢!

【问题讨论】:

  • 为什么一切都是关系,而 messages_read 不是?
  • 我认为这是“正确的方式”。 Dialog、Manager 和 Message 是实体——我有它们的模型。 dialog_manager - 只是用于链接对话框和管理器的数据透视表。 messages_read - 存储读取数据的表。我不想用它做模型。但是,如果你认为这是构建应用程序的正确方法,我也会制作 ManagerRead 模型。附言添加了有关“经理”表的信息
  • 哦,好的。也应该按照你的方式工作。别介意我。
  • 为什么在$join->on('messages.id', '=', 'message_id')->on('messages_read.manager_id', '=', DB::raw($managerId)) 中需要DB::raw()
  • 你打电话给$manager->dialogs()->withCount(['unread_messages']);unread_messages 不是关系。所以这行不通。您可能必须这样做:dd($manager->dialogs()->unread_messages->addSelect(DB::raw('COUNT('*'))->get());

标签: php mysql laravel eloquent


【解决方案1】:

不要在关系中使用 id(你不在任何上下文中)

最简单的方法:

$manager = Manager::with(['dialogs' => function($query){
   $query->withCount('messages as unread_messages_count' => function($query){
            $query->whereNull('read_at');
        });
}])->find($id);

$unread_message = $manager->dialogs->sum('unread_messages');

【讨论】:

  • 感谢您的回答!但是您的示例仅使用 messages 表,而不使用 messages_read 表。问题是 - 我必须从messages_read 表中获取数据,而不是从messages 表中获取数据。消息表根本没有“read_at”字段
  • 然后在您的已读和未读消息之间创建一个关系,并在您的查询中添加 ->has('unreadMessages')
【解决方案2】:

感谢各位的帮助。我为 unread_messages 函数找到了这个解决方案:

return $this->messages()->where(function($query) use ($managerId) {
     $query->where('manager_id', '!=', $managerId)->orWhereNull('manager_id');
})->whereNotExists(function($query) use ($managerId)
     {
         $query->select(DB::raw(1))
             ->from('messages_read')
             ->whereRaw('messages_read.message_id = messages.id')->where('manager_id', '=', DB::raw($managerId));
     });

也许它不是最佳的,但它有效。也许有一天我会在 laravel 有更多经验时重写它。

【讨论】:

    猜你喜欢
    • 2022-07-14
    • 2015-06-07
    • 2018-08-28
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多