在我的mySQL数据库中,我有3个表:
我可以选择多种成分ID,例如。 [1,50,60,7,3] 我需要找到我可以准备的鸡尾酒,只有这些成分列表。可能含有较少的成分,但它们必须存在于我的成分列表中[1,50,60,7,3]。
我宣布了我的ManyToMany关系,我创建了我的模型,一切正常,现在我尝试使用ORM创建我的查询:
$ids = [1,50,60,7,3];
$coktails = Cocktail::has('ingredients','<=',count($ids))
->whereHas('ingredients',function($q) use ($ids){
$q->whereIn('ingredients.id',$ids);
})
->get();
我也试过了:
$coktails = Cocktail::has('ingredients','<=',count($ids))
->whereHas('ingredients',function($q) use ($ids){
foreach ($ids as $id){
$q->where('ingredients.id',$id);
}
})
->get();
总是一个错误的计数,我知道我的问题在于我的关闭,但我无法找到它。
谢谢
答案 0 :(得分:2)
在您的示例中,您的目标成分列表为[1,50,60,7,3]
。想象一下,你有一种鸡尾酒需要成分[1, 2]
。
根据您当前的逻辑:
has('ingredients', '<=', count($ids))
将匹配,因为2 <= 5
和whereHas('ingredients', function($q) use ($ids) { $q->whereIn('ingredients.id', $ids); })
将匹配,因为子查询将返回id 1的记录,默认情况下,whereHas
仅查找至少一条记录。所以,根据这个逻辑,将返回成分[1, 2]
的鸡尾酒,而这不是你想要的。
您真正想要的是确保您只能获得没有任何不在您的目标ID列表中的成分的鸡尾酒。 [1, 50]
应该匹配,因为它是一个子集,但[1, 2]
不应该匹配,因为成分2
不在原始集合中。
要处理此问题,您需要使用whereDoesntHave
方法和whereNotIn
方法的组合。
$ids = [1,50,60,7,3];
$cocktails = Cocktail::whereDoesntHave('ingredients', function($q) use ($ids) {
$q->whereNotIn('ingredients.id', $ids);
})
->get();
这句话说&#34;得到所有没有成分列表中没有的成分的鸡尾酒。&#34; [1, 50]
会匹配,因为它没有任何不在列表中的成分。但是,[1, 2]
将不匹配,因为它的成分不在列表中(2
)。