Laravel 5 Eloquent 多对多关系查询

Laravel 5 Eloquent ManyToMany relationship query

在我的 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();

总是计数错误,我知道我的问题出在我的 whereHas Closure 上,但我找不到它。

谢谢

在您的示例中,您的目标成分列表是 [1,50,60,7,3]。想象一下,您有一种需要成分 [1, 2].

的鸡尾酒

根据您目前的逻辑:

  • has('ingredients', '<=', count($ids)) 将匹配,因为 2 <= 5
  • whereHas('ingredients', function($q) use ($ids) { $q->whereIn('ingredients.id', $ids); }) 将匹配,因为子查询将 return id 1 的记录,并且默认情况下,whereHas 仅查找至少一条记录。

因此,根据该逻辑,含有 [1, 2] 成分的鸡尾酒将 returned,这不是您想要的。

您真正要寻找的是确保您只获得不含任何不在目标 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();

此语句表示 "get all the cocktails that don't have an ingredient that is not in this list of ingredients." [1, 50] 将匹配,因为它没有任何不在列表中的成分。但是,[1, 2] 不会匹配,因为它确实有一个不在列表中的成分 (2)。