我目前正在用PHP设计和实现一个RESTful API。然而,我一直没有成功地实现我的初始设计。
GET /users # list of users
GET /user/1 # get user with id 1
POST /user # create new user
PUT /user/1 # modify user with id 1
DELETE /user/1 # delete user with id 1
到目前为止都很标准,对吧?
我的问题是第一个GET /users。我正在考虑在请求体中发送参数以过滤列表。这是因为我想要能够指定复杂的过滤器而不得到一个超长的url,如:
GET /users?parameter1=value1¶meter2=value2¶meter3=value3¶meter4=value4
相反,我想要这样的东西:
GET /users
# Request body:
{
"parameter1": "value1",
"parameter2": "value2",
"parameter3": "value3",
"parameter4": "value4"
}
这是更可读的,让你有很大的可能性来设置复杂的过滤器。
不管怎样,file_get_contents('php://input')不会为GET请求返回请求体。我还尝试了http_get_request_body(),但我使用的共享主机没有pecl_http。反正也不确定是否有用。
我发现了这个问题,并意识到GET可能不应该有请求体。这有点不确定,但他们建议不要这么做。
所以现在我不知道该怎么办。如何设计RESTful搜索/过滤功能?
我想我可以使用POST,但这似乎不太RESTful。
如果你的初始API是完全RESTful的,也不要太担心(特别是当你只是在alpha阶段)。首先让后端管道工作。你总是可以做一些URL转换/重写来映射,迭代地改进,直到你得到足够稳定的东西来进行广泛的测试(“测试”)。
您可以定义uri,其参数是根据uri本身的位置和约定编码的,前缀是您知道将始终映射到某个对象的路径。我不懂PHP,但我认为这样的工具是存在的(因为它存在于其他语言的web框架中):
.ie。使用param[i]=value[i]对i=1进行“user”类型的搜索。4在商店#1(与value1,value2,value3,…作为URI查询参数的简写):
1) GET /store1/search/user/value1,value2,value3,value4
or
2) GET /store1/search/user,value1,value2,value3,value4
或如下所示(虽然我不推荐,稍后再说)
3) GET /search/store1,user,value1,value2,value3,value4
对于选项1,将所有前缀为/store1/search/user的uri映射到搜索处理程序(或任何PHP名称),默认搜索store1下的资源(相当于/search?location=store1&type=user)。
根据API记录和执行的约定,参数值1到4用逗号分隔,并按此顺序显示。
选项2将搜索类型(在本例中为user)添加为位置参数#1。任何一种选择都只是表面上的选择。
选择3也可以,但我不喜欢。我认为在某些资源中进行搜索的能力应该在URI本身中先于搜索本身显示出来(就好像在URI中清楚地表明在资源中进行搜索一样)。
与在URI上传递参数相比,这样做的优点是搜索是URI的一部分(因此将搜索视为资源,其内容可以(也将会)随时间而改变的资源)。缺点是参数顺序是强制的。
一旦你做了这样的事情,你可以使用GET,它将是一个只读资源(因为你不能POST或PUT它-当它被GET'ed时它会被更新)。它也是一种只有在调用时才存在的资源。
还可以通过将结果缓存一段时间或使用DELETE删除缓存来为其添加更多语义。然而,这可能与人们通常使用DELETE的目的背道而驰(因为人们通常使用缓存头来控制缓存)。
如何去做是一个设计决策,但这是我要做的。它并不完美,而且我相信在某些情况下,这样做并不是最好的选择(特别是对于非常复杂的搜索条件)。
如果你的初始API是完全RESTful的,也不要太担心(特别是当你只是在alpha阶段)。首先让后端管道工作。你总是可以做一些URL转换/重写来映射,迭代地改进,直到你得到足够稳定的东西来进行广泛的测试(“测试”)。
您可以定义uri,其参数是根据uri本身的位置和约定编码的,前缀是您知道将始终映射到某个对象的路径。我不懂PHP,但我认为这样的工具是存在的(因为它存在于其他语言的web框架中):
.ie。使用param[i]=value[i]对i=1进行“user”类型的搜索。4在商店#1(与value1,value2,value3,…作为URI查询参数的简写):
1) GET /store1/search/user/value1,value2,value3,value4
or
2) GET /store1/search/user,value1,value2,value3,value4
或如下所示(虽然我不推荐,稍后再说)
3) GET /search/store1,user,value1,value2,value3,value4
对于选项1,将所有前缀为/store1/search/user的uri映射到搜索处理程序(或任何PHP名称),默认搜索store1下的资源(相当于/search?location=store1&type=user)。
根据API记录和执行的约定,参数值1到4用逗号分隔,并按此顺序显示。
选项2将搜索类型(在本例中为user)添加为位置参数#1。任何一种选择都只是表面上的选择。
选择3也可以,但我不喜欢。我认为在某些资源中进行搜索的能力应该在URI本身中先于搜索本身显示出来(就好像在URI中清楚地表明在资源中进行搜索一样)。
与在URI上传递参数相比,这样做的优点是搜索是URI的一部分(因此将搜索视为资源,其内容可以(也将会)随时间而改变的资源)。缺点是参数顺序是强制的。
一旦你做了这样的事情,你可以使用GET,它将是一个只读资源(因为你不能POST或PUT它-当它被GET'ed时它会被更新)。它也是一种只有在调用时才存在的资源。
还可以通过将结果缓存一段时间或使用DELETE删除缓存来为其添加更多语义。然而,这可能与人们通常使用DELETE的目的背道而驰(因为人们通常使用缓存头来控制缓存)。
如何去做是一个设计决策,但这是我要做的。它并不完美,而且我相信在某些情况下,这样做并不是最好的选择(特别是对于非常复杂的搜索条件)。