Nesting & Relationships
resource มีความสัมพันธ์ระหว่างกัน และโครงสร้างของ URI สามารถสื่อความสัมพันธ์บางส่วนเหล่านั้นได้ เคล็ดลับคือ nest ให้มากพอที่จะเข้าใจง่ายโดยไม่สร้าง path ที่ nest ลึกจนเปราะบาง
Sub-resources
หัวข้อที่มีชื่อว่า “Sub-resources”เมื่อ resource หนึ่งเป็นของอีก resource หนึ่งอย่างชัดเจน ให้ nest ลงไปหนึ่งระดับ:
GET /articles/42/comments # comments of article 42POST /articles/42/comments # add a comment to article 42GET /users/7/articles # articles written by user 7flowchart LR A[/articles/42/] --> C[/articles/42/comments/] C --> CI[/articles/42/comments/9/]
ควร nest ลึกแค่ไหน
หัวข้อที่มีชื่อว่า “ควร nest ลึกแค่ไหน”หยุดที่หนึ่งระดับ หรือบางครั้งสองระดับ path อย่าง /users/7/articles/42/comments/9/reactions/3 นั้นอ่านยากและผูก resource ที่ควรยืนอยู่ได้ด้วยตัวเองเข้าด้วยกัน พอ sub-resource มีตัวตน (identity) ของตัวเองแล้ว ก็ให้ URI ระดับ top-level ไปเลย แล้ว link ถึงกันแทนที่จะ nest ลึกลงไปอีก:
GET /comments/9 # the comment as a first-class resourceGET /articles/42/comments # still fine as a scoped collectionLinking
หัวข้อที่มีชื่อว่า “Linking”แทนที่จะฝัง (embed) ทุกอย่างลงไป ให้ส่งกลับ reference ที่ client สามารถตามไปได้:
| Nesting Strategy | เหมาะกับ | ไม่เหมาะกับ |
|---|---|---|
/users/\{id\}/orders (nested) | resource ที่ ownership ชัดเจน | resource ที่ exist อิสระ |
/orders?userId=\{id\} (flat + filter) | resource ที่ query จากหลาย context | ownership ที่ต้องการ enforce |
/orders/\{id\} (flat direct) | access resource โดยตรงด้วย ID | ต้องการ parent context |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”Nesting ลึกเกิน อาการ:
/companies/\{id\}/departments/\{id\}/teams/\{id\}/members/\{id\}/tasks/\{id\}- URI ยาวมาก ยากต่อการ maintain และ document
- จำกัดที่ 2 ระดับ หรือ flatten เป็น
/tasks/\{id\}แล้ว filter ด้วย query param
Relationship ที่ Many-to-Many แต่ทำ Nested อาการ:
/users/\{id\}/tags/\{id\}— user มีหลาย tag, tag มีหลาย user- nested ทำให้ ownership ไม่ชัด — DELETE tag จาก user หรือ delete tag ทั้งหมด?
- ใช้ junction resource:
POST /user-tagsด้วย{ userId, tagId }
💡 ตัวอย่างจากของจริง
GitHub API:
/repos/\{owner\}/\{repo\}/issues— 2 ระดับ ชัดเจน/repos/\{owner\}/\{repo\}/issues/\{number\}/comments— 3 ระดับ maxStripe API:
/customers/\{id\}/payment_methods— nested สำหรับ owned resource/payment_methods/\{id\}— access โดยตรงได้เมื่อรู้ ID