Laravel多对多关系查询

3
我有一个API用于跟踪照片和标签。每张照片可以有N个标签,而一个标签可以与N张照片相关联。这是通过3个表完成的:
  • 照片表。
  • 标签表。
  • 照片和标签关系表。
现在我正在努力获取所有带有一组标签的照片,我的想法是向我的API发送一个标签列表请求,并获得至少拥有所有标签的照片列表。
我一直在尝试使用whereIn操作符。
这是我的代码(现在全部硬编码):
$photos = Photo::whereHas('tags', function (Builder $query) {
            $query->whereIn('tag', ['a5', 'mate', 'Brillante']);
        })->get();

        return response()->json($photos, 200);

当我执行它时,它返回与一个标签匹配的所有照片,而我只需要拥有所有请求标签的照片(在这个例子中是a5,mate)。

我正在使用Laravel 9。

编辑:

如Tim Lewis建议的那样,我已经尝试了循环:

$tags = array("a5", "mate", "Brilante");
        $photoQuery = Photo::query();

        foreach($tags as $tag) {
            \Log::debug($tag);
            $photoQuery->whereHas('tags', function($query) use ($tag) {
                return $query->where('tag', $tag);
            });
        }

        $photos = $photoQuery->get();

现在它返回了一个空列表,我认为是因为它正在寻找仅具有我在数组中硬编码的3个标签的照片。

编辑2:

看起来这些更改是正确的,但出于某种原因,Postman没有显示出这些更改的任何结果,也没有解决我的问题。


whereIn() 匹配任何一个选项,而不是所有选项。如果您需要匹配所有选项,则可能需要 3 个 whereHas() 子句,每个子句检查一个标签。 - Tim Lewis
这是作为API工作的,我不知道我的用户在每个请求中会发送多少标签,有其他方法吗? - jcobo1
1
这仍然可以工作;你只需要使用循环动态地添加whereHas()子句。我看到你说目前是硬编码的,但是将其变为动态的并不困难。 - Tim Lewis
好的,我会按照你建议的使用循环。 - jcobo1
请尝试使用赋值操作符:$photoQuery = $photoQuery->whereHas(...);。同时,请检查您的拼写:BrillanteBrilante - Tim Lewis
1个回答

2

由于whereIn()方法匹配提供的任何值,而不是所有值,因此您需要进行修改。为每个标签指定一个whereHas()子句应该可以解决问题:

$photoQuery = Photo::query();
foreach ($request->input('tags') as $tag) {
  $photoQuery = $photoQuery->whereHas('tags', function ($query) use ($tag) {
    return $query->where('tag', $tag);
  });
}
$photos = $photoQuery->get();

根据您的API发送的标签(假设通过$request变量作为'tags' => []数组),此查询将包括每个标签的whereHas()子句,并仅返回具有所有指定标签的Photo记录。请保留HTML标记。

我已经尝试过了,但返回的是一个空列表。我认为这是因为它只在查找具有我指定的3个标签的照片?它应该将至少具有这3个或更多标签的所有照片都带给我。我将把这段新代码添加到原始问题中。 - jcobo1
你手动检查过发送的标签是否至少应用于1张照片吗?这段代码不应该关心是否附加了其他未指定的标签;只要包含了你发送的所有标签,它就应该返回信息。也许可以调整你的问题,包括一个数据库截图,显示标签、它们的ID和在数据库中的关联。 - Tim Lewis
1
另外,尝试将 ->get() 替换为 ->toSql(),以查看实际执行的查询语句。 - Tim Lewis
1
现在正在工作,我认为是Postman上的某些问题。谢谢Tim! - jcobo1
语法不错,代码看起来很易读。它使用阻抗概念(数据库)吗? - UserOfStackOverFlow
1
@Whats91356Java 谢谢,这只是Laravel使用定义的模型和关系进行“Eloquent”查询的语法。我没有计算机科学或数据库管理员背景,所以我不确定在这种情况下“阻抗概念”是什么意思。 - Tim Lewis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接