我有这个数据透视表:
+----+---------+-----------------+
| id | user_id | conversation_id |
+----+---------+-----------------+
| 1 | 2 | 48 |
+----+---------+-----------------+
| 2 | 1 | 48 |
+----+---------+-----------------+
我正在尝试找到一种方法来检测两个用户是否在同一个对话中,如果是,则返回对话。有些像:
Conversation::with([1, 2]); // should return conversation 48
我的Conversation
课程如下:
class Conversation extend Eloquent {
public function users() {
return $this->belongsToMany('User');
}
public function messages(){
return $this->hasMany('Message');
}
}
到目前为止,我有下面的代码,但它很笨拙而且非常无效,并且认为必须有一些更干净的Laravel方式:
class Conversation {
public static function user_filter(Array $users) {
$ids = array();
foreach ($users as $user)
$ids[$user->id] = $user->id;
sort($ids);
foreach (self::all() as $conversation){ // loop through ALL conversations (!!!)
$u_ids = $conversation->users->lists('id');
sort ( $u_ids );
if ($u_ids === $ids)
return $conversation;
}
return null;
}
}
用法:
Conversation::user_filter([User::find(1), User::find(2)]); // returns conversation 48
有什么想法吗?
答案 0 :(得分:3)
让我们首先看一下如何实际检索结果,而不必通过所有类型的数组进行循环...
您可以使用whereHas
功能过滤关系。我们可以应用条件,如果它们符合模型的相关记录,它将包含在结果中。
$conversations = Conversation::whereHas('users', function($q){
$q->where('user_id', 1);
})->get();
对于一个用户来说就是这样。对于两个或更多用户,它基本相同。您只需要链接whereHas
s
$conversations = Conversation::whereHas('users', function($q){
$q->where('user_id', 1);
})
->whereHas('users', function($q){
$q->where('user_id', 2);
})->get();
现在这不是很优雅。您可以创建query scope来为您完成所有工作并保持控制器代码清洁。在Conversation
public function scopeWithUsers($query, array $userIds){
foreach($userIds as $id){
$query->whereHas('users', function($q) use ($id){
$q->where('user_id', $id);
});
}
return $query;
}
用法:
$conversations = Conversation::withUsers([1,2])->get();
$conversations = Conversation::withUsers([1,2,3,4])->get();
$conversations = Conversation::withUsers([1])->get();
如果它只应该是一个,请使用first()
代替get()
答案 1 :(得分:0)
这样的事情应该有效。
class Conversation {
public static function user_filter(Array $users) {
$ids = array();
foreach ($users as $user) {
$ids[] = $user->id;
}
return self::select("conversation_id")->whereIn("user_id", $ids)->groupBy("conversation_id")->havingRaw("count(*) = " . count($ids))->get();
}
}
答案 2 :(得分:0)
与给定用户进行所有对话。
Conversation::whereHas('users', function($query) use ($userids) {
$query->whereIn('user_id', $userids);
})->get();
如果你需要特别的,你可以:
Conversation::whereHas('users', function($query) use ($userids) {
$query->whereIn('user_id', $userids);
})->whereId($id)->first();