通过 Laravel 关系查询 HasManyThrough 检索相关记录
Posted
技术标签:
【中文标题】通过 Laravel 关系查询 HasManyThrough 检索相关记录【英文标题】:Query HasManyThrough Laravel relation retrieving related records 【发布时间】:2017-11-18 14:28:34 【问题描述】:考虑到 Laravel 指南中的基本示例 Has Many Through 关系,我尝试直接查询具有 100 类型帖子的雄辩的国家(只是一个示例)。
countries
id - integer
name - string
users
id - integer
country_id - integer
name - string
posts
id - integer
user_id - integer
title - string
type_id - integer
posts 中的 type_id 是我的特殊情况..
因此,我在国家模型中创建了一个关系,该关系通过用户创建了与帖子的关系。我想要实现的结果是一个国家列表以及每个国家/地区内该国家/地区用户创建的帖子。
//Country.php
public function posts()
return $this->hasManyThrough(
'Post', 'User', 'country_id', 'user_id'
);
我能够以其他方式复制我想要达到的结果,但我想知道为什么下面的雄辩查询没有返回预期的结果:
$postsGroupedByCountries = Country::with([
'posts' => function ($query)
$query->where('type_id', 100);
])->get();
查询的返回是几个国家,所有帖子都没有数据。使用 Laravel Eloquent 进行此查询的正确方法是什么?
第一次尝试:
$postsGroupedByCountries = Country::whereHas('posts', function ($query)
$query->where('type_id', 100);
)->get();
第二次尝试:
$postsGroupedByCountries = Country::whereHas('posts', function ($query)
$query->where('type_id', 100)->groupBy('posts.id');
)->get();
第三次尝试:
$postsGroupedByCountries = Country::whereHas('posts', function ($query)
$query->where('type_id', 100);
)->get();
$postsGroupedByCountries = $postsGroupedByCountries ->map(function($country)
$country->load('posts');
return $country;
);
而且我已经尝试在负载内部使用带有 where 的闭包。但它也没有奏效。结果是一样的。
【问题讨论】:
【参考方案1】:您急于加载每个国家/地区的所有帖子,这就是您看到所有帖子的原因。我会尝试将查询修改为:
$postsGroupedByCountries = Country::whereHas('posts', function ($query)
$query->where('type_id', 100)
)->get();
看看你得到了什么回报。
【讨论】:
但我想提供加载帖子的数据。哪里会做呢?我认为 whereHas 只是条件。 我认为它会将加载的帖子返回给您,试一试,看看结果如何。我一直在参考这篇文章,顺便说一句:***.com/questions/30231862/… 帖子未加载。我猜想 where has 是延迟加载。我需要在雄辩的查询之后进行 foreach 并调用 $country->posts 来获取它并放入国家/地区。 使用之后,如果我尝试访问它的关系 ($country->posts
),我会得到与第一次尝试相同的结果。很多不连贯的帖子。
尝试将 groupBy 添加到嵌套查询中,例如:$query->where('type_id', 100)->groupBy('posts.id')
【参考方案2】:
您必须使用with
和whereHas
进行查询。 whereHas
将限制 Country
查询仅显示具有指定 id 帖子的国家,但不会在结果中加载这些帖子。然后with()
将在结果中急切加载posts
,但是因为它在第一个查询执行后被调用,它不知道whereHas
约束,并且由于它没有通过任何约束,它将加载所有帖子各国。要使用相同的约束加载 Country
的帖子,您还需要将其传递给 with
方法。
所有放在一起看起来像:
$countries = Country::whereHas('posts', function($query)
return $query->where('type_id', 100);
)
->with(['posts' => function($query)
return $query->where('type_id', 100);
])
->get();
【讨论】:
以上是关于通过 Laravel 关系查询 HasManyThrough 检索相关记录的主要内容,如果未能解决你的问题,请参考以下文章
通过 Laravel 关系查询 HasManyThrough 检索相关记录