2

关于 URL 设计的新手 Play 框架问题:我正在寻找更适合 Play 框架的习惯,尽管我认为这在某些方面可能是一个更一般的 URL 设计问题。

这些不是我的真实实体,但假设您有可以编辑的集合,例如:

GET /collections/:id controllers.Collections.edit(id: Long)
POST /collections/:id controllers.Collections.update(id: Long)
POST /collections/:id/delete controllers.Collections.delete(id: Long)

现在每个集合都可以有项目。这些项目在数据库中具有自己的 ID,但它们也具有带有外键约束的父集合的 ID。

所以我可以看到有这些:

GET /collections/:collection/items controllers.Items.list(collection: Long)
GET /collections/:collection/items/new controllers.Items.create(collection: Long)
POST /collections/:collection/items controllers.Items.save(collection: Long)

但是随后要编辑或删除已经存在的单个项目,因此我可以仅使用项目 ID 获取项目的集合 ID,我想要这个:

GET /items/:id controllers.Items.edit(id: Long)
POST /items/:id controllers.Items.update(id: Long)
POST /items/:id/delete controllers.Items.delete(id: Long)

还是我想做这样的事情?:

GET /collections/:collection/items/:id controllers.Items.edit(collection:Long, id: Long)
POST /collections/:collection/items/:id controllers.Items.update(collection:Long, id: Long)
POST /collections/:collection/items/:id/delete controllers.Items.delete(collection:Long, id: Long)

我想到的一个想法是如果我使用复合键(无论好坏)。我是否应该使用第二组来将接口与我只需要具有当前架构的项目 ID 的事实隔离开来?或者第二套完全是假的和浪费的?从理论上讲,它允许现有项目的 URL 具有错误的集合 ID(您可以检查,但仍然如此)。

(注意我会在上面使用更多的 RESTful PUT/DELETE,但我现在使用的是普通的 HTML 表单)

(对不起,如果这是一个常见问题解答,我真的找不到这样的东西)

4

1 回答 1

2

在 Play 2.0 中没有内置的自动控制器/动作路由(就像在 Play 1.x 中一样),所以事实上没有定义的路由模式。

这意味着,你可以做你自己的模式,只有你必须确保路由是有效的。有一些我的想法和做法:

您不应该使用 ie 冗余前缀,例如/collections/or /items/

http://domain.tld/presentation/collections/1/items/1

导致如果用户将删除地址栏中的最后一段,它将指向无处

http://domain.tld/presentation/collections/1/items (404 as no such route)

而是尝试构建准备好提供合理内容的 URL,即使用户会修改它:

http://domain.tld/presentation/1/1 (display single item 1 in collection 1)
http://domain.tld/presentation/1   (list of items in collection 1)
http://domain.tld/presentation     (list of collections)
http://domain.tld/                 (main page)

当然,在这种情况下,最好创建字符串键来识别数据库中的记录以使链接用户友好:

http://domain.tld/t-shirts/autumn-2012/play-geeks-shirt-red-xl
http://domain.tld/tasks/project-1/prepare-correct-routes

当然,如果您不信任字符串标识符,您可以像 Stack Overflow 那样建立链接,其中倒数第二段是数字 ID,最后一段只是搜索引擎和人类的字符串,对搜索记录没有任何意义(打开那个链接http://stackoverflow.com/questions/12719857,它也会给你带来当前的问题)

我个人更喜欢在前端没有附加数字 ID 的字符串标识符,但是它需要检查它在所选路径中是否唯一并将附加数据存储在 DB 中。

对于后端,我建议在开头使用稳定的前缀和单独的控制器(为整个控制器设置一个授权规则比注释许多操作更容易)。当然,使用字符串标识符来编辑记录是多余的工作:

http://domain.tld/admin/1         (list of items from first collection)
http://domain.tld/admin/1/edit    (edit form for first collection)
http://domain.tld/admin/1/1       (edit form for item 1 in first collection \), 
       it hasn't got subitems so there's no need to display its preview first

http://domain.tld/admin/1/1/edit  (alternative, same action as above)
       in this case you should prepare redirect from admin/1/1 to admin/1/1/edit,
       otherwise you'll get same form available on two URL's (for each record) 
       which can be confusing

delete, save,update动作通常作为最后一段(尽管为了更加 RESTful,它应该被声明为 ie. DELETE route without /deletesuffix at the end)

 http://domain.tld/admin/1/1/delete

无论如何,如果您打算使用 IE GET 来删除记录,最好在 URL 中添加一些计算的哈希值,并在从数据库中删除对象之前对其进行检查。它不是授权机制,因为它有更好的功能,它只是允许您通过手动编写 url 来确保不会意外删除记录,因此它可以是记录 ID 的示例 MD5 哈希:

 http://domain.tld/admin/1/1/delete?confirm=a76fe878988ced8...

最后,如果集合和项目都没有严格关联,您可以在单独的“url-spaces”中创建链接以编辑它们:

 http://domain.tld/admin/collections/1/edit
 http://domain.tld/admin/items/1/edit
 http://domain.tld/admin/contacts/1/edit
 http://domain.tld/admin/offices/1/edit...

在这种情况下,如果您准备正确的导航链接就足够了,如果您拥有干净舒适的导航,您很可能不需要太在意您作为管理员会操纵 URL。

于 2012-10-04T10:06:54.133 回答