我目前正在为现有的PHP应用程序设计API,为此我正在研究REST作为一种合理的架构方法.
我相信我对关键概念有一个合理的把握,但我很难找到任何解决了对象层次结构和REST的人.
这是问题......
在[application]业务对象层次结构中,我们有:
Users
L which have one-to-many Channel objects
L which have one-to-many Member objects
Run Code Online (Sandbox Code Playgroud)
在应用程序本身中,我们使用延迟加载方法根据需要使用这些对象的数组填充User对象.我相信OO术语这是对象聚合,但我已经看到各种命名不一致,并且不关心开始关于精确命名约定的战争.
现在,请考虑我有一些松散耦合的对象,我可能/可能不会填充,具体取决于应用程序的需要.
从REST的角度来看,我试图确定方法应该是什么.这是我目前的想法(仅考虑GET暂时):
选项1 - 完全填充对象:
GET api.example.com/user/{user_id}
Run Code Online (Sandbox Code Playgroud)
读取User对象(资源)并返回User对象,其中包含预加载和编码的所有可能的Channel和Member对象(JSON或XML).
PROS:减少对象数量,不需要遍历对象层次结构
CONS:对象必须完全填充(昂贵)
选项2 - 填充主对象并包含指向其他对象资源的链接:
GET api.example.com/user/{user_id}
Run Code Online (Sandbox Code Playgroud)
读取User对象(资源)并返回用户对象填充的用户数据和两个列表.
每个列表引用适当的(子)资源即
api.example.com/channel/{channel_id}
api.example.com/member/{member_id}
Run Code Online (Sandbox Code Playgroud)
我认为这接近(或确切地说)超媒体的含义 - 客户端可以获得其他资源(只要我明智地标记它们).
PROS:客户端可以选择加载下属或以其他方式更好地分离对象作为REST资源
CONS:获取辅助资源所需的进一步行程
选项3 - 启用递归检索
GET api.example.com/user/{user_id}
Run Code Online (Sandbox Code Playgroud)
读取User对象并包含指向子对象列表的链接,即
api.example.com/user/{user_id}/channels
api.example.com/user/{user_id}/members
Run Code Online (Sandbox Code Playgroud)
/ channels调用将返回表单中的通道资源列表(如上所示):
api.example.com/channel/{channel_id}
Run Code Online (Sandbox Code Playgroud)
PROS:主要资源暴露了去哪里获得subodinates而不是它们是什么(更多RESTful?),没有要求预先让下属,下级列表生成器(/ channels和/ member)提供接口(类似方法)制作响应更多的服务就像.
缺点:现在需要三个调用来完全填充对象
选项4 - (重新)考虑REST的对象设计
我正在重新使用[现有]应用程序对象层次结构并尝试将其应用于REST - 或者更直接地,为它提供API接口.
也许REST对象层次结构可能不同,或者新的RESTful思想可能暴露了现有对象设计的局限性.
对上述任何想法表示欢迎.
非常感谢
保罗
我正在为RESTful API设计自定义媒体类型,并研究了一些"标准"链接关系的类型和语义含义,以使我的设计具有一定的引导性.
为了演示这个问题,让我说我有一个资源,我可以执行标准的读取,更改,删除方法,并分别使用GET,PUT和DELETE的HTTP惯用法来实现这些方法.
我可以合理地(重新)使用RFC5023中定义的"编辑"链接关系(来自IANA链接注册表),其中规定:
"..."edit"的值指定href属性的值是可编辑成员条目的IRI.当出现在atom:entry中时,href IRI可用于检索,更新和删除资源由该条目代表...."
通过这种方式,用户代理可以理解具有"编辑"关系的链接将允许资源为GET,PUT和DELETEd.
然而,这里存在的问题是,如果编辑资源状态使得资源现在仅支持GET和DELETE操作,则"编辑"关系不再精确.
为了保持我需要的精度i)选项A:指定仅支持GET&DELETE的另一个(复合)链接关系,或ii)选项B:为每个可能的状态转移指定单独的链接并使用适当的链接来指示允许的国家转移.后一种方法提供精确但似乎过于冗长.
或者,(选项C)我可以保持"编辑"关系并接受缺乏精确性,即链接将传达GET,PUT,DELETE语义,但尝试PUT的用户代理将遇到HTTP错误' 405 - 方法不允许'.但是,我对这种方法不满意,因为它意味着客户端不支持状态转换.
总之,问题是平衡链接关系的一般性和精确性的最明智的方法是什么?