我正在尝试创建一个如下所示的api JSON响应结构:
[
{
"id": 1,
"name": "jon abraham",
"email": "jonabe2442@gmail.com",
"image": "/images/avatar-default.jpg",
"messages": [
{message: 'hello!', user_id: 1},
{message: 'yo!', user_id: 3}
]
},
{
"id": 2,
"name": "sherry hopkins",
"email": "shop2663@gmail.com",
"image": "/images/avatar-default.jpg",
"messages": [
{message: 'hey!', user_id: 2},
{message: 'hi!', user_id: 3}
]
}
]
JSON响应表示属于当前登录用户所属的同一公司的所有用户的列表。它还将显示该用户与当前登录用户之间的消息数组(如果没有消息,则为空数组)。
我设法创建了大部分我想要的api结构,除了消息部分,因为在为私人聊天建立适当的数据库结构/雄辩关系时遇到了麻烦。
这是我的私人聊天数据库结构。
会话
| id | participant_1_id | participant_2_id
Conversation_messages
| id | sender_id | receiver_id |文本
这是我的控制器代码,它返回api:
public function userWithMessages
{
$user = Auth::user();
$company_ids = $user->companies()->pluck('companies.id')->toArray();
$users = User::join('company_user', 'users.id', 'company_user.user_id')
->join('companies', 'company_user.user_id', 'companies.id')
->whereIn('companies.id', $company_ids)
->select('users.name', 'users.email', 'users.image')
->get();
return response()->json($users, 200);
}
我正在尝试编写我的查询,以便我没有遇到n + 1问题,但我似乎无法找到与用户对话的关系。原因是,在会话表中,我不知道user_id是participant_1_id
还是participant_2_id
,这意味着我不能使用hasMany
关系。
有没有办法可以从用户那里获取有关当前登录用户的消息数据,而无需编写foreach循环并查询每个用户(n + 1)问题。
答案 0 :(得分:2)
我建议使用以下数据库结构。这不仅支持用户之间的多个对话,还支持每个对话超过两个参与者,从而允许您进行群组对话。
user
- id
- first_name
- last_name
...
conversations
- id
- created_at
- updated_at
conversation_user
- id
- conversation_id
- user_id
- created_at
message
- id
- conversation_id
- user_id
- message
- created_at
- updated_at
上述模式的模型定义和关系如下所示:
<?php
class User extends Eloquent
{
public function conversations()
{
return $this->belongsToMany(Conversation::class)->latest('updated_at');
}
public function messages()
{
return $this->hasMany(Message::class)->latest();
}
}
class Conversation extends Eloquent
{
public function participants()
{
return $this->belongsToMany(User::class)->oldest();
}
public function messages()
{
return $this->hasMany(Message::class)->latest();
}
}
class Message extends Eloquent
{
public function conversation()
{
return $this->belongsTo(Conversation::class);
}
public function sender()
{
return $this->belongsTo(User::class);
}
}
要查找所有与其对话的用户,您可以使用以下查询。这将使用两个查询来查找所有用户和对话。
$users = User::with('conversations')->get();
要查找包含其邮件的所有用户,您可以使用以下查询。这将使用两个查询来查找所有用户和对话。
$users = User::with('messages')->get();
要查找具有对话和消息的所有用户,您可以合并上述查询。这将使用三个查询来查找所有用户,对话和消息。但请注意,消息不会嵌套在会话下方。
$users = User::with('conversations', 'messages')->get();
编辑:以下内容将为您提供所有用户以及他们与当前用户进行的任何对话。如果您还在conversations.messages
来电中加入with()
,那么您也可以在这些对话中收到消息。虽然这很快就会成为一个庞大的数据集。
$user = Auth::user();
$users = User::with([
'conversations' => function ($query) use ($user) {
return $query->whereHas('user', function ($query) use ($user) {
return $query->where('user_id', $user->id);
});
},
'conversations.messages',
])
->get();
我很乐意回答您对上述问题的任何后续问题。