用于在restful API中对结果进行高级过滤的URL设计


URL design for advanced filtering of results in restful API

让我们举一个普通的资源示例,您可以使用PHP内置的restful API进行建模。

  • 一个车库有多辆汽车和多个机械师
  • 一辆汽车只有一个车库
  • 一个机修工有多辆车和多个车库(他是个工作狂!)

所以逻辑上说我们的终点应该是

/v1/garages  
/v1/garages/1234
/v1/mechanics
/v1/mechanics/1234
/v1/cars
/v1/cars/1234

如果我们想得到1234车库的所有汽车,我们会使用GET /v1/garages/1234/cars

如果我们想要34号车库里的所有12号机修工的车,我们会使用GET /v1/mechanics/12/garage/34/cars

但是,如果我们想要56和78号车库的所有汽车呢
我有一些想法,但我能想到的最好的是GET /v1/cars?garage=[id=[56,78]]

这将使我们能够通过GET /v1/cars?garage=[paint=yellow,bonnet=[material=carbon]]&color=green&doors=[2,4]

这似乎是一个合理的想法吗?或者我会遇到嵌套变得复杂的问题吗?这应该足够容易用PHP解析吗?

据我所知,我的另一个想法是Json,所有Json在url中都是有效的,所以

GET /v1/cars?{"color":"green","doors":[2,4],"garage":{"paint":"yellow","bonnet":{"material":"carbon"}}}

这使得开发人员非常容易使用,因为现在几乎所有的编程语言都支持json,而在API端,我们只能使用json_decode($_SERVER[''QUERY_STRING]),所以使用json有什么问题吗?

第三个想法"创建搜索"

我的意思是我们使用

POST /cars/search将上述Json作为请求的后数据,只需返回搜索的ID,然后可以通过GET /cars/search/{id}将结果提取到该ID,这将减轻我的复杂性,并避免请求的8kb限制(这是API,不用于浏览器地址栏)。但我担心,如果我这样做,那么它会违背顶级GET /v1/cars端点的目的吗?

感谢#laravel-irc频道的乐于助人,我与他们进行了长时间的交谈,我们得到了一个似乎有效的答案。

我们选择这个答案是基于以下几点:

  • 易于阅读
  • 查询的力量
  • 平面度(易于解析)
  • 易于过滤

基本要求是

GET /v1/cars?color=green
            &doors=2,4
            &garage[paint]=yellow
            &garage[bonnet][material]=carbon

当与以下代码组合时

$query = array();
parse_str($_SERVER['QUERY_STRING'], $query);

吐出一个数组,如下所示,可以在API中轻松迭代以进行过滤:)

Array
(
  [color] => green
  [doors] => 2,4
  [garage] => Array
    (
      [paint] => yellow
      [bonnet] => Array
        (
          [material] => carbon
        )
    )
)