如何在 Laravel 4 RESTful API 中实现多对多关系

4
我希望能够在Laravel 4中实现类似于此问题中所要求的内容,其中一个player/资源可以拥有多个team/,反之亦然。

在理想情况下,我应该能够查询

players/1/teams

并获取以下JSON:

{ player: { 
    id: 1, name: 'Bob', sport: 'Curling', teams: [
        { id: 1, name: 'Northern Curling Soc.', age: 2}, 
        { id:2, name: 'Southern Curling Soc.', age: 4 }
    ] 
}

或者

调用teams/{id}/players并获取相关结果。

很显然,如果我使用Laravel的视图,我可以简单地调用$player->teams,一切都会很好,但这是为了JSON API,所以所有内容都需要提前处理好。

我还需要能够对相关结果进行分页,虽然这可能是一个不同的问题。

如何在Laravel中实现这一点呢?

感谢任何帮助!

2个回答

5

Laravel 4增加了对嵌套资源路由的支持。这些路由非常好用,似乎非常适合这个场景。

基本上,在添加“直接”资源控制器的同时,您需要为嵌套资源添加路由。在这种情况下,除了:

Route::resource('players', 'PlayersController');  // players/#
Route::resource('teams', 'TeamsController');      // teams/#

...你需要:

Route::resource('players.teams', 'PlayerTeamsController');  // players/#/teams/#
Route::resource('teams.players', 'TeamPlayersController');  // teams/#/player/#

在控制器中,通常接收单个ID作为参数的方法现在将接收两个参数(顺序由您的路由定义):

class PlayerTeamsController extends Controller {

    public function show($player_id, $team_id) {

    }

}

您可以使用继承来避免控制器之间的代码冗余。

1
通过API,只需包含关系并返回对象(在Laravel 4中)。L4会自动将数据格式化为JSON输出。
return Player::with( [ 'teams' ] )->get();

它会提供基本上完全符合您要求的格式 :)

谢谢。我在其他地方也做过这个。JSON很棒!问题是,我如何以一般化的方式路由到它(我不想为所有资源设置和维护单独的路由)? - djb
玩家控制器能够响应玩家本身的资源吗?例如,player/1/teams player/1/clubs等等。 - Oddman
1
这是一个独立的问题,但我建议不要这样做。更好的方法是查询特定团队,即:GET /teams?player_id=5 而不是 GET /player/5/teams/这使您的API更简单,路由/控制器等更易于维护,并且是各种文章中推荐的方法。我建议阅读“Teach a dog to rest”(谷歌搜索)。 - Oddman
@Oddman 推荐使用玩家/5/队伍的方法来表示关系,这在 Teach a dog to REST 中实际上是被推荐的。查询参数更适合于过滤器(获取所有 25 岁以上的玩家= /players?min_age=25)。我自己正在寻找使用 Laravel 实现这个的方法。 - idmadj
@idmadj 哇,我一定是错过了那个!如果你在 Laravel 中得到了一个好的解决方案,请告诉我,我很想看看 :) - Oddman
啊,好的,我看到了。不过我发现它存在一些问题,尤其是重复的代码/路由。我想知道是否可能让团队控制器代表两个资源,并在有player_id时稍微改变功能呢? - Oddman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接