0

假设我们在项目管理 SaaS 中的User模型和模型之间存在 M:M 关系。Project自然地,我们有一个将用户映射到项目的数据透视表。如果用户离开或项目经理将该用户从项目中删除,则删除条目。

即使最终结果基本相同(即条目被删除),我想通过定义两个单独的 API 端点来区分这两个操作会更好,如下所示:

用户离开项目

路线DELETE /users/{id}/projects/{id}

UserProjectController@destroy($id)$id项目的行动

项目经理删除用户

路线DELETE /projects/{id}/participants/{id}

ProjectParticipantController@destroy($id)$id用户的动作

我应该忽略 Cruddy by Design 和 RESTful 设计原则,leave() join() remove()而是简单地定义动作并在 URI 中使用动词吗?像这样:

POST /projects/{id}/join

POST /projects/{id}/leave

POST /projects/{id}/participants/{id}/remove

4

2 回答 2

0

需要考虑的事情:您将如何在网络上进行操作?

即使最终结果基本相同(即条目被删除),我想通过定义两个单独的 API 端点来区分这两个动作会更好

所以在网络上,你很可能有两种不同的表单用于“实现相同的结果”,但这并不一定意味着表单应该针对不同的资源

POST /foo
Content-Type: application/x-www-form-urlencoded

action=UnsubscribeUser&otherArguments=....
POST /foo
Content-Type: application/x-www-form-urlencoded

action=CancelProject&otherArguments=....

“一种资源或两种资源”不是对与错的问题,而是取舍的问题。

POST /projects/{id}/join
POST /projects/{id}/leave
POST /projects/{id}/participants/{id}/remove

这也“很好”;再次,这是一个权衡问题。机器不关心您的标识符在 URI 中是否有动词。

他们确实有点关心读取的标识符是否与写入的标识符相同。请参阅RFC 7234

但是完全合理的说法是,在访问日志或浏览器历史记录中具有语义上重要的 URI 拼写对于我们的长期成功比缓存失效更重要。


请牢记 DELETE(在 HTTP 上下文中)与 SQL 上下文中的 DELETE 不同。我们正在谈论两个具有自己语义的不同名称空间。

HTTP DELETE是通过网络域传输文档。您的处理程序的实现包括 SQL DELETE 的事实完全无关紧要。

相对较少的资源允许使用 DELETE 方法——它的主要用途是远程创作环境,用户对其效果有一定的指导。

可以使用 POST

于 2021-09-10T13:25:07.087 回答
0

join, leave,remove可以说是 RPC 而不是 REST。数据透视表等是域的实现方式,与在域级别工作的 API 调用者无关。URL 如何映射到您的域模型?

如果Project有一个或多个User为什么不直接使用

/projects/{id}/

Project管理关于和Participant实例的一切?

User是在一个Project但只有当

/projects/{id}/participants/{id}

已被调用。

FWIW,

DELETE /users/{id}/projects/{id}

看起来它正在删除对象所拥有的Project实例,但不使用该术语。也许会是:UserProjectparticipantsUser

DELETE /users/{id}/projects/{id}/participants

为了与领域模型保持一致。

Project但是,仅用于管理Project实例似乎要容易得多。使用APIUser从 a中删除 a似乎是一种方便,使后端复杂化并且与术语不匹配。那将意味着只有和课程。ProjectUserProjectUserControllerProjectController

您必须考虑 a 是否Participant id与 a 相同,User id以及数据透视表是否处理该问题,但这不会影响 API。API 应该是您的域模型的直观表示。

于 2021-09-10T10:05:55.080 回答