Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Api 包含或不包含资源子级的RESTful方式?_Api_Rest_Nested - Fatal编程技术网

Api 包含或不包含资源子级的RESTful方式?

Api 包含或不包含资源子级的RESTful方式?,api,rest,nested,Api,Rest,Nested,假设我有一个team对象,它有一个name属性、一个city属性和一个players属性,其中players属性是一个可能有许多玩家的数组。这在一个SQL数据库中表示,该数据库包含一个团队表和一个玩家表,其中每个玩家都有一个名称和一个团队id 基于这个简单的数据结构构建一个RESTful api,我怀疑在点击/teams/:id时是否有明确的规则,返回对象是否应该/可能包括一个玩家列表 我有一个观点,需要展示一支球队,以及球员的名字,所以: 1:是否应该/teams/:id将场景后面的两个表连接

假设我有一个
team
对象,它有一个
name
属性、一个
city
属性和一个
players
属性,其中
players
属性是一个可能有许多玩家的数组。这在一个SQL数据库中表示,该数据库包含一个
团队
表和一个
玩家
表,其中每个玩家都有一个
名称
和一个
团队id

基于这个简单的数据结构构建一个RESTful api,我怀疑在点击
/teams/:id
时是否有明确的规则,返回对象是否应该/可能包括一个玩家列表

我有一个观点,需要展示一支球队,以及球员的名字,所以:

1:是否应该
/teams/:id
将场景后面的两个表连接起来,并返回完整的
team
对象,以及一个players属性,即名称和id的数组

2:是否应该将
/teams/:id
连接到场景后面的两个表中,并返回
team
对象,该对象带有一个players属性,即一个仅包含id的数组,然后必须逐个查询到
/players/:id

3:应该打两个电话吗,一个打给
/teams/:id
,一个打给
/teams/:id/players

4:是否应该像这样使用查询字符串
/teams/:id?fields=姓名、城市、球员

如果选择2个或3个,那么如何处理这样的情况,即一个团队也可能有多个城市,从而在DB中生成另一个
城市
表以保持其正常化?然后是否应在
/teams/:id/cities
处创建新端点


创建RESTful API时,是数据库中的规范化数据结构决定了API中的端点吗?

通常使用RESTful API时,最好由用例决定API的端点,而不一定是数据结构

如果您有时只需要团队,有时只需要团队中的玩家,有时同时需要这两个,我会有3个不同的调用,可能类似于
/teams/:id
/players/:teamid
玩家团队/:teamid
(或类似的调用)

您希望以这种方式执行此操作的原因是,它将需要为任何给定页面发出的HTTP请求数量降至最低。在所有典型的性能问题中,HTTP请求数量过多通常是最常见的性能问题之一,也是最容易避免的问题之一


话虽如此,您也不想疯狂到创建过度膨胀的API。仔细考虑典型的用例,并对其进行调用。不要只是为了实现你能想到的所有可能的组合。记住。

我建议如下:

GET /teams
{
    "id" : 12,
    "name" : "MyTeam"
    "players" :
    {
        "self" : "http://my.server/players?teamName=MyTeam"
    },
    "city" :
    {
        "self" : "http://my.server/cities/MyCity"
    }
}

GET /cities
GET /cities/{cityId}
GET /players
GET /players/{playerId}
然后,您可以使用URI调用以获取所需的任何其他相关资源。如果希望灵活地嵌入值,可以使用?展开,例如:

GET /teams?expand=players
{
    "id" : 12,
    "name" : "MyTeam"
    "players" :
    {
        "self" : "http://my.server/players?teamName=MyTeam",
        [
            {
                 "name" : "Mary",
                 "number" : "12"
            },
            {
                 "name" : "Sally",
                 "number" : "15"
            }
         ]
    },
    "city" :
    {
        "self" : "http://my.server/cities/MyCity"
    }
}

非常感谢你的回答。/player teams/:teamid方法很有趣,以前从未见过。与/teams/:id?字段=姓名、城市、球员?清晰度相比,这种方法有什么优势。我更喜欢使用更干净、查询字符串更少的方法,因为我认为它们更清晰。如果你只看路线
player teams/:team id
,你就知道你能通过什么和不能通过什么,并且对你能得到什么有一个合理的猜测。使用查询字符串,您并不总是知道a)可以传递哪些字段,b)这些字段的有效值是什么。如果您需要那么多端点,您是否会以许多端点结束,例如
玩家城市
团队城市
城市团队玩家
?非常可能。如果你有很多方法需要对你的信息进行切分,另一种方法可能是有一个更通用的端点,你可以在其中应用过滤器,比如
players?filter.city=louisville
还要注意“需要”这个词的用法。正如我在最初的回答中所说的,不要只是实现你能想到的任何组合。只实现你真正要使用的那些。谢谢,看起来很棒。为了确保我理解您的设计理念,
/teams/:id/players
可能仍然是一个端点,当只需要一个团队的玩家列表时,当需要团队信息和球员列表时,
/teams/:id?expand=players
将是一个端点?我不会同时实现查询字符串和/teams/:id/players。你应该选一个你喜欢的。如果你同时做这两件事,那么你必须支持多种方式永远做同一件事。如果我想要一个团队中的所有玩家,我将使用可选的查询参数?teamName=MyTeam提供/players作为端点。至于第二位,是的,我可以选择/teams/:id?expand=players。