如何在 Laravel 中使用超过 3 个表的 'hasManyThrough'?

How to use 'hasManyThrough' with more than 3 tables in Laravel?

docs 中所述,当前的 hasManyThrough 可以在您有类似 country > users > posts

的情况下使用

这会导致 Country::whereName('xx')->posts; 这很好,但如果我有更多的东西,比如

country > cities > users > posts 甚至

country > cities > towns > users > posts

然后你会如何实现类似的东西,这样你就可以写出与上面相同的东西

Country::whereName('xx')->posts;Town::whereName('xx')->posts;

遗憾的是没有一个简单的解决方案,所以这是我找到的

1- 将另一个 table 外国 id 添加到 post table 并坚持使用 hasMany & 属于,例如

posts
    id - integer
    country_id - foreign
    // etc...
    title - string

2- 在每个 table 上使用 hasManyThrough 除了 userpost 因为没有必要除非你想去更深,例如

countries
    id - integer
    name - string

cities
    id - integer
    country_id - foreign
    name - string

towns
    id - integer
    city_id - foreign
    name - string

users
    id - integer
    town_id - foreign
    name - string

posts
    id - integer
    user_id - foreign
    title - string

- so lets try with the 2nd option

1- 照常设置您的 hasMany & belongsTo 关系

2- 在模型上设置 hasManyThrough

3-为了实现上面的例子Country::whereName('xx')->posts我们在country模型

中添加了另一种方法
// because Country::find($id)->towns, return an array
// so to get all the posts we have to loop over that
// and return a new array with all the country posts
public function posts()
{
    $posts = [];

    foreach ($this->towns as $town) {
        $posts[] = $town->posts;
    }

    return $posts;
}

4- 因为整个事情都是通过 foreign_id 进行的,所以我们通过 id[=52= 进行搜索] 而不是像 Country::find($id)->posts()

这样的 name

这是我所做的。我对@ctfo 的回答做了一些修改,所以它会 return 为 collection.

public function posts()
{
    $posts = collect();

    foreach ($this->towns->get() as $town) {
        $post = $town->posts();
        if ( $post->count() ) $posts = $posts->merge( $post );
    }

    return $posts;
}

我希望这可以帮助到任何通过的人。

我创建了 HasManyThrough 无限级别的关系:Repository on GitHub

安装完成后可以这样使用:

class Country extends Model {
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function posts() {
        return $this->hasManyDeep(Post::class, [City::class, Town::class, User::class]);
    }
}