我正在创建一个消息传递应用程序,我需要检查是否已存在具有特定用户列表的对话(不多也不少)。我有这个模型:
class Conversation{
public function users(){
return $this->belongsToMany('App\User');
}
public function messages(){
return $this->hasMany('App\Message');
}
}
我有这些表格:
会话:
用户:
conversation_user:
我想发布这样的帖子请求:
{
"users": [1,4,6], <- user ids
"message": "Some message"
}
如果已与所有用户1,4,6进行对话,则应将该消息添加到该对话中,以避免在数据库中出现重复的对话。否则,我将与指定的用户进行新的对话。 这是迄今为止我能做到的最好的事情:
$existing_conversation = $user->conversations()->whereHas('users',
function($query) use ($data){
$query->whereIn('user_id', $data['users']);
}
)->has('users', '=', count($data['users']));
但它只返回具有用户数组中用户数量的对话。它忽略了内部查询..
有没有人对此有所了解? :)
答案 0 :(得分:1)
您可以尝试以下查询
$existing_conversation = $user->conversations()->wherePivotIn('user_id', $data['users'])->has('users', count($data['users'])->get();
Haven经过测试,我认为应该工作。
更新
不是一个非常优雅的解决方案,但它有效。您可以在控制器中添加一些辅助方法,如
//Get user's conversations with no of users equal to count($data['users']);
protected function get_conversations_with_equal_users(User $user, array $user_ids)
{
return $user->conversations()
->wherePivotIn('user_id', $user_ids)
->has('users', '=', count($user_ids))
->get();
}
//Get the id of a user conversation with exactly same users as $data['users'] if it exists otherwise it will return 0;
protected function get_existing_conversation_id(User $user, array $user_ids)
{
$existing_conversation_id = 0;
$user_conversations_with_equal_users = $this->get_conversations_with_equal_users($user, $user_ids);
foreach($user_conversations_with_equal_users as $conv)
{
$ids = [];
foreach($conv->users as $user)
{
$ids[] = $user->id;
}
if($this->array_equal($user_ids, $ids))
{
$existing_conversation_id = $conv->id;
}
}
return $existing_conversation_id;
}
//Function to compare two arrays for equality.
protected function array_equal($a, $b) {
return (
is_array($a) && is_array($b) &&
count($a) == count($b) &&
array_diff($a, $b) === array_diff($b, $a)
);
}
您可以在控制器中使用以下内容来获取用户的现有对话(如果存在)
$existing_conversation_id = $this->get_existing_conversation_id($user, $data['users']);
if($existing_conversation_id)
{
$existing_conversation = Conversation::with('users')
->whereId($existing_conversation_id)
->get();
}