首页 > 解决方案 > 在 RESTful API 中管理 m:n 关系的最佳实践

问题描述

我正在设计一个 API,我想注意 RESTful 方法。因为在我的研究中,大多数类似的文章都提到了球员和球队,我会坚持下去。在这种情况下,一名球员一次可以拥有多个球队,但必须至少拥有一个球队。如果一名球员隶属于多个球队,则您无法删除该球员。

为此,如果您想创建一个播放器,您需要:

POST /teams/{id}/players

直接 POST /players 不会考虑到玩家有一个团队,所以它是不允许的。

如果你想删除一个播放器,你可以这样做:

DELETE /players/{id}

只有当玩家只隶属于一支球队时才应该这样做,但如果球员在多支球队中,则应该拒绝(在这种情况下,您需要解除除一支球队之外的所有球队的链接)。

现在我有不同的方法来处理创建和删除团队和玩家之间的新链接:

  1. POST /teams/{id}/players/{id}
  2. PUT /teams/{id}/players/{id}
  3. POST /players-teams(正文中有players_id和teams_id)

一个。DELETE /teams/{id}/players/{id}

湾。DELETE /players-teams/{id}

不同解决方案的一些想法:

广告 1. GET 不会引用相同的信息

广告 2. 我没有提供关系的 ID...

广告 3. 我应该提供GET /teams/{id}/players-teamsGET /players/{id}/players-teams- 或GET /players/{id}/teams-players

广告 不会删播放器吗?

广告 b。谁会知道关系的ID?

标签: restapimany-to-many

解决方案


鉴于一个玩家可以存在于多个团队中,并且团队与玩家的关系可能会发生变化,我认为为此有 2 个单独的命名空间是很常见的:

players/ <- list of all players
players/{id} <- a single player
teams/ <- list of all teams
teams/{id} <- a single team

这里缺少的是球队和球员之间的关系。处理此问题的一个好方法可能是让玩家代表团队中的链接。这种团队资源的虚构表示:

{
   name: "team awesome",
   _links: {
     self : { href: "/teams/A" },
     players: [
       { href: "/players/1" },
       { href: "/players/2" },
     ]
  }
}

如果将关系表示为团队资源上的链接,则将玩家删除或添加到团队的行为与向团队发送PUT资源并添加/删除这些链接相同。上述格式使用 HAL。

但是,如果您只想获得完整的球员名单和他们的信息怎么办?绝对可以将“团队中的所有玩家”表示为单独的资源,可能在:

/teams/{id}/players

我仍然会确保此资源中的所有玩家都链接到/players/{id}而不是/team/{id}/players/{id}.

尽管不允许单个实体出现在系统中的多个 url 上,但这可能会让用户感到困惑,因为它们看起来像是单独的资源。


推荐阅读