将 hasManyThrough 应用于更深层次的关系

Applying hasManyThrough to deeper relationships

Laravel 文档似乎表明 hasManyThrough 声明只能用于两个级别的关系 "deep"。更复杂的关系呢?比如一个User有很多Subject,每个Subject有很多Deck,每个Card有很多Card。使用 hasManyThrough 声明获取属于 User 的所有 Deck 很简单,但是属于 User 的所有 Card 呢?

如评论中所述,hasManyThrough 不支持这种级别的特异性。您可以做的其中一件事是 return 一个反方向的查询构建器实例:

//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();

嗯,实际上最好的解决方案是将额外的列添加到卡片 table - user_id,如果您经常需要为用户获取所有卡片。

Laravel 为 2-depth 关系提供 Has-Many-Through 关系,因为这是非常广泛经常使用的关系。 对于Laravel不支持的关系,需要自己想出最好的table关系。

无论如何,为了您的目的,您可以使用以下代码 snap 使用您当前的关系模型为用户获取所有卡片。

Assumption

  • 用户与 Deck 有 hasManyThough 关系,

因此项目模型将具有以下代码:

 public function decks()
    {
        return $this->hasManyThrough('Deck', 'Subject');
    }
  • 卡片组与卡片有 hasMany 关系

Code

$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 无限级别的关系:Repository on GitHub

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

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

    public function cards() {
        return $this->hasManyDeep(Card::class, [Subject::class, Deck::class]);
    }
}