ข้ามไปยังเนื้อหา

Nesting & Relationships

resource มีความสัมพันธ์ระหว่างกัน และโครงสร้างของ URI สามารถสื่อความสัมพันธ์บางส่วนเหล่านั้นได้ เคล็ดลับคือ nest ให้มากพอที่จะเข้าใจง่ายโดยไม่สร้าง path ที่ nest ลึกจนเปราะบาง

เมื่อ resource หนึ่งเป็นของอีก resource หนึ่งอย่างชัดเจน ให้ nest ลงไปหนึ่งระดับ:

GET /articles/42/comments # comments of article 42
POST /articles/42/comments # add a comment to article 42
GET /users/7/articles # articles written by user 7
flowchart LR
  A[/articles/42/] --> C[/articles/42/comments/]
  C --> CI[/articles/42/comments/9/]
การ 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 resource
GET /articles/42/comments # still fine as a scoped collection

แทนที่จะฝัง (embed) ทุกอย่างลงไป ให้ส่งกลับ reference ที่ client สามารถตามไปได้:

JavaScript
Nesting Strategyเหมาะกับไม่เหมาะกับ
/users/\{id\}/orders (nested)resource ที่ ownership ชัดเจนresource ที่ exist อิสระ
/orders?userId=\{id\} (flat + filter)resource ที่ query จากหลาย contextownership ที่ต้องการ 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 ระดับ max

Stripe API:

  • /customers/\{id\}/payment_methods — nested สำหรับ owned resource
  • /payment_methods/\{id\} — access โดยตรงได้เมื่อรู้ ID
โดยปกติแล้วการ nest URI ควรลึกแค่ไหน?
เมื่อ sub-resource มีตัวตนที่มั่นคงเป็นของตัวเองแล้ว คุณควร:
`POST /articles/42/comments` สื่อถึงอะไร?