使用嵌套中间表

时间:2013-12-03 19:37:24

标签: orm laravel laravel-4 eloquent eager-loading

我正在使用Laravel 4并尝试设置表结构来处理以下问题。

  • 我有3张桌子:玩家,团队和季节
  • 每个赛季,我将分配多个队伍,每个队伍将分配多个队员。
  • 我需要维护每个季节的历史数据,所以我不能直接连接表格,因为更改基本玩家/队伍表会影响所有季节。

我联系了四季 - >使用中间表teams_in_season的团队表如下:

class Season extends \Eloquent
{
    public function teams()
    {
        return $this->belongsToMany('Team', 'teams_in_season');
    }
}

按预期工作。当我想设置播放器分配时出现问题。当然,我想将团队与玩家联系起来,所以我的思路是我需要从另一个中间表创建一个中间表。例如:

seasons -> teams_in_season -> players_in_teams -> players

如果我去了四季 - >玩家,除了我不能以那种方式加载它之外,它会起作用。

seasons -> players_in_season -> players

$season->teams->players->get();

基本上,用户输入数据的方式是创建一个赛季,分配球队,将球员分配给球队,然后最终添加得分。输入的所有数据都需要维护,因此中间表是必要的。

所以,这是我的问题:

  1. 我可以像这样嵌套/链接中间表吗?
  2. 有没有更好的方法来设置我想要实现的目标?

2 个答案:

答案 0 :(得分:1)

这是一个难题。您需要将球员与球队和赛季之间的数据透视表相关联。出于这个原因,我可能会将其设置为自己的模型。

<强>关系

  • Season hasMany SeasonTeam
  • SeasonTeam属于团队
  • SeasonTeam属于ToMany Player

急切加载

以下是如何使用严格的关系方法和急切加载来列出所有球队的球员名单。这是4个查询。

$season = Season::with('seasonTeams.players', 'seasonTeams.team')->find(1);

foreach ($season->seasonTeams as $seasonTeam)
{
    echo $seasonTeam->team->name;

    foreach ($seasonTeam->players as $player)
    {
        echo $player->name;
    }
}

<强>加入

我不会在此处提取详细信息,但您也可以在查询构建器中使用联接来拉动在特定赛季中参与球队的球员。看看下面的链接。

http://four.laravel.com/docs/queries#joins

答案 1 :(得分:0)

我尝试了一些不同的想法(包括科林的答案),但决定在这里采取不同的路线。主要的是我觉得使用$season->seasonTeams->teams()有点难以理解。此外,尝试将中间表链接到另一个中间表也感觉有点奇怪。我想出的解决方案是:

对于团队而言,我坚持原始的季节设计 - &gt; teams_in_seasons - &gt;允许我使用$season->teams()查找实例化团队的团队以及其中所需的任何数据透视数据,使用以下关系建立季节模型:

public function teams()
{
    return $this->belongsToMany('Team', 'teams_in_season');
}

与团队相反:

public function seasons()
{
    return $this->belongsToMany('Season', 'teams_in_season');
}

对于玩家而言,我决定将数据透视表teams_in_season连接到季节和团队表,而不是链接现有数据透视表players_in_teams。为了将这些连接在一起,我决定使用查询生成器在Team模型上构建我自己的查询:

public function players($season_id, $team_id)
{
    return DB::table('players')
        ->select(DB::raw('players.*'))
        ->join('players_in_team', 'players.id', '=', 'players_in_team.player_id')
        ->where('season_id', '=', $season_id)
        ->where('team_id', '=', $team_id)
        ->orderBy('last_name');
}

这将使我能够按照以下方式急切加载给定赛季球队的球员:

$team->players($season->id, $team->id)->get()

这或许有点不正统,但它适用于我的目的。我找不到另一种方法,对我来说逻辑上有道理。它还有一个副作用,允许我在Seasons模型上添加一个方法,这将允许我急切加载给定赛季的所有球员,如:

Season::find(1)->players