将 hasManyThrough 应用于更深层次的关系
Posted
技术标签:
【中文标题】将 hasManyThrough 应用于更深层次的关系【英文标题】:Applying hasManyThrough to deeper relationships 【发布时间】:2017-05-10 03:21:08 【问题描述】:Laravel 文档似乎表明 hasManyThrough
声明只能用于两层“深”的关系。更复杂的关系呢?例如,一个User
有很多Subject
s,每个Deck
s 有很多Deck
s,每个Card
s 很多。使用hasManyThrough
声明让所有Deck
s 属于User
很简单,但是属于User
的所有Card
s 呢?
【问题讨论】:
I asked this same question 几年前。 HasManyThrough 只是一个捷径。就目前而言,没有用于访问远距离关系的内置机制。 【参考方案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 与 Card 有 hasMany
关系
代码
$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
的所有卡片。
【讨论】:
以上是关于将 hasManyThrough 应用于更深层次的关系的主要内容,如果未能解决你的问题,请参考以下文章