简体   繁体   English

查询 HasManyThrough Laravel 关系检索相关记录

[英]Query HasManyThrough Laravel relation retrieving related records

Considering the basic example Has Many Through relationship in the Laravel guide, I'm trying to query directly with eloquent, countries with posts from type 100 (just an example).考虑到 Laravel 指南中的基本示例 Has Many Through 关系,我尝试使用 eloquent 直接查询,这些国家的帖子来自类型 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

type_id in posts is my peculiar case..帖子中的 type_id 是我的特殊情况..

So, I created a relationship in the country model that creates a relation with posts through users.因此,我在国家 model 中创建了一个关系,该关系通过用户创建了与帖子的关系。 The result that I want to achieve is a list of countries and within each country the posts created by users of that country.我想要实现的结果是一个国家列表以及每个国家/地区内该国家/地区用户创建的帖子。

//Country.php
public function posts()
{
    return $this->hasManyThrough(
        'Post', 'User', 'country_id', 'user_id'
    );
}

I was able to replicate the result I want to achieve in other ways, but I would like to know why the eloquent query below does not return the expected result:我能够以其他方式复制我想要实现的结果,但我想知道为什么下面的 eloquent 查询没有返回预期的结果:

   $postsGroupedByCountries = Country::with([
        'posts' => function ($query) {
            $query->where('type_id', 100);
        }
    ])->get();

The return of the query are several countries with all posts without data.查询的返回是几个国家,所有帖子都没有数据。 What is the correct way to do this query with Laravel Eloquent?使用 Laravel Eloquent 执行此查询的正确方法是什么?

First try:第一次尝试:

$postsGroupedByCountries = Country::whereHas('posts', function ($query) {
    $query->where('type_id', 100);
})->get();

Second try:第二次尝试:

$postsGroupedByCountries = Country::whereHas('posts', function ($query) {
    $query->where('type_id', 100)->groupBy('posts.id');
})->get();

Third try:第三次尝试:

$postsGroupedByCountries = Country::whereHas('posts', function ($query) {
    $query->where('type_id', 100);
})->get();

$postsGroupedByCountries = $postsGroupedByCountries ->map(function($country){
     $country->load('posts');
     return $country;
});

And I've already tried inside the load to use a closure with where as well.而且我已经尝试在负载内部也使用带有 where 的闭包。 But it also did not work.但它也没有奏效。 The result is the same.结果是一样的。

You have to use with and whereHas for the query. 您必须使用withwhereHas进行查询。 whereHas is going to constrain the Country query to only show countries with posts from the specified id but does not load those posts in the results. whereHas将限制Country查询仅显示具有指定id的帖子的国家,但不会在结果中加载这些帖子。 with() will then eager load the posts in the results BUT since it is called after the first query executes it does not know about the whereHas constraint and since it has been passed no constraints it will load all of the posts for each country. 然后with()会急切加载结果中的posts但因为它在第一个查询执行后调用它不知道whereHas约束,并且由于它没有传递任何约束,它将加载每个国家的所有帖子。 To load the Country 's posts with the same constraints you would need to pass that to the with method as well. 要使用相同的约束加载Country的帖子,您还需要将其传递给with方法。

All put together it would look like: 所有放在一起看起来像:

$countries = Country::whereHas('posts', function($query) {
    return $query->where('type_id', 100);
})
->with(['posts' => function($query) {
    return $query->where('type_id', 100);
}])
->get();

You are eager loading all the posts with every country, that is why you're seeing them all. 你渴望加载每个国家的所有帖子,这就是你看到它们的原因。 I would try modifying the query to this: 我会尝试将查询修改为:

$postsGroupedByCountries = Country::whereHas('posts', function ($query) {
    $query->where('type_id', 100)
})->get();

See what that gets you returned. 看看你得到了什么。

// Country.php
public function postsOfTypeHundred()
{
    return $this->hasManyThrough('Post', 'User', 'country_id', 'user_id')
        ->where('type_id', 100);
}
/**
 * Laravel ^9.15
 * In Controller 
 */
$countries = Country::withWhereHas('postsOfTypeHundred')->get();
/** Created By */
$countries[0]->posts[0]->user->name

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM