【问题标题】:Applying hasManyThrough to deeper relationships将 hasManyThrough 应用于更深层次的关系
【发布时间】:2017-05-10 03:21:08
【问题描述】:
Laravel 文档似乎表明 hasManyThrough 声明只能用于两层“深”的关系。更复杂的关系呢?例如,一个User 有很多Subjects,每个Decks 有很多Decks,每个Cards 很多。使用hasManyThrough 声明让所有Decks 属于User 很简单,但是属于User 的所有Cards 呢?
【问题讨论】:
标签:
php
laravel
eloquent
relationship
【解决方案1】:
如 cmets 中所述,hasManyThrough 不支持此级别的特异性。您可以做的一件事是返回一个相反方向的查询构建器实例:
//App\User;
public function cards()
{
Card::whereHas('decks', function($q){
return $q->whereHas('subjects', function($q){
return $q->where('user_id', $this->id);
});
});
}
我们将从Cards -> Decks -> Subjects 出发。 subjects 应该有一个 user_id 列,然后我们可以锁定它。
当从用户模型调用时,它会如此轻松地完成:
$user->cards()->get();
【解决方案2】:
我创建了一个无限级别的HasManyThrough 关系:Repository on GitHub
安装后,可以这样使用:
class User extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function cards() {
return $this->hasManyDeep(Card::class, [Subject::class, Deck::class]);
}
}
【解决方案3】:
好吧,实际上最好的解决方案是将额外的列放入 Card 表 - user_id,如果您经常需要为用户获取所有卡片。
Laravel 为 2-depth 关系提供 Has-Many-Through 关系,因为这是非常广泛使用的关系。
对于 Laravel 不支持的关系,你需要自己找出最佳的表关系。
出于您的目的,您可以使用以下代码快照以任何方式使用您当前的关系模型为用户获取所有卡片。
假设
- 用户与 Deck 有
hasManyThough 关系,
所以项目模型将有以下代码:
public function decks()
{
return $this->hasManyThrough('Deck', 'Subject');
}
代码
$deck_with_cards = $user->decks()->with("cards")->get();
$cards = [];
foreach($deck_with_cards AS $deck) {
foreach ($deck->cards as $c) {
$cards[] = $c->toArray();
}
}
现在$cards 拥有$user 的所有卡片。