如何在 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 除了 user
和 post
因为没有必要除非你想去更深,例如
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]);
}
}
如 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 除了 user
和 post
因为没有必要除非你想去更深,例如
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()
这是我所做的。我对@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]);
}
}