
กำลังโหลด...

กำลังโหลด...

เมื่อกี้น้องใช้ req.params ไปแล้วแบบงูๆ ปลาๆ วันนี้มาทำความเข้าใจให้ครบ
เพราะเดี๋ยวจะมีอีก 2 ช่องทาง (query กับ body) แล้วถ้าแยกไม่ออกว่าอันไหนใช้เมื่อไหร่ จะออกแบบ API มั่วไปหมด
เป้าหมายของ Mission นี้: ใช้ req.params รับค่าที่ฝังอยู่ใน URL ได้อย่างมั่นใจ
จบ Mission นี้คุณจะ
req.params ให้ค่าเป็นชนิดอะไรและต้องแปลงเมื่อไหร่เวลาเราเขียน "/books/:id" เครื่องหมาย : บอก Express ว่า "ตรงนี้เป็นช่องว่าง อะไรมาก็รับ
แล้วเก็บชื่อว่า id"
app.get("/books/:id", ...)
|
+-- ช่องว่างชื่อ id
ยิง GET /books/7 -> req.params = { id: "7" }
ยิง GET /books/abc -> req.params = { id: "abc" }
ยิง GET /books/หนังสือ -> req.params = { id: "หนังสือ" }
:id รับอะไรก็ได้ ไม่ได้จำกัดว่าต้องเป็นตัวเลข — นี่คือสาเหตุของกับดักลำดับ route
ที่เจอมา 3 ครั้งแล้ว
flowchart LR
A["GET /users/12/books/5"] --> B["route pattern<br/>/users/:userId/books/:bookId"]
B --> C["req.params = {<br/> userId: '12',<br/> bookId: '5'<br/>}"]
C --> D["Number() แปลงก่อนใช้"]
style C fill:#1e3a5f,stroke:#38bdf8,color:#fff
ASCII แบบจับคู่ตำแหน่ง
Pattern: /users/:userId/books/:bookId
| |
URL จริง: /users/ 12 /books/ 5
| |
ผลลัพธ์: req.params.userId = "12"
req.params.bookId = "5"
Express จับคู่ ตามตำแหน่ง ไม่ใช่ตามชื่อ — ชื่อหลัง : เป็นแค่ชื่อที่เราตั้งเองเพื่อเรียกใช้
app.get("/books/:id", (req, res) => {
const books = readBooks();
const id = Number(req.params.id);
const book = books.find((b) => b.id === id);
if (!book) return res.status(404).json({ error: "ไม่พบหนังสือเล่มนี้" });
res.json(book);
});
ทุก route ยังขึ้นต้นด้วย
readBooks()เหมือน Chapter 3 — Chapter นี้เปลี่ยนแค่ วิธีรับค่าจาก Client ไม่ได้เปลี่ยนวิธีเก็บข้อมูล
// GET /books/1997/แฮร์รี่ -> หาหนังสือปี 1997 ที่ชื่อมีคำว่า แฮร์รี่
app.get("/books/:year/:keyword", (req, res) => {
const { year, keyword } = req.params; // destructure ได้เหมือน object ปกติ
const results = readBooks().filter(
(b) => b.year === Number(year) && b.title.includes(keyword),
);
res.json(results);
});
ปัญหา: Number("abc") ได้ NaN ซึ่งเทียบกับอะไรก็ไม่ตรง แล้วเราจะได้ 404 — ซึ่งพอใช้ได้
แต่ถ้าอยากบอกผู้ใช้ให้ชัดว่า "id ต้องเป็นตัวเลข" ให้ตอบ 400 แทน
app.get("/books/:id", (req, res) => {
const id = Number(req.params.id);
if (!Number.isInteger(id)) {
return res.status(400).json({ error: "id ต้องเป็นตัวเลขจำนวนเต็ม" });
}
const book = readBooks().find((b) => b.id === id);
if (!book) return res.status(404).json({ error: "ไม่พบหนังสือเล่มนี้" });
res.json(book);
});
Number.isInteger(NaN) เป็น false จึงใช้ดักได้ทั้ง "abc" และ "1.5" ในทีเดียว
400 vs 404 ในเคสนี้: ทั้งคู่ยอมรับได้
/books/abc→ 400 = "คุณส่งรูปแบบผิด"/books/999→ 404 = "รูปแบบถูก แต่ไม่มีของ" แยกแบบนี้ช่วยให้ Frontend แสดงข้อความต่างกันได้
ลองตอบในใจว่า req.params จะได้อะไร
| Route Pattern | URL ที่ยิงมา | req.params = ? |
|---|---|---|
/books/:id |
/books/42 |
{ id: "42" } |
/books/:id |
/books/42/reviews |
ไม่ตรง → ไปหา route อื่น |
/users/:uid/books/:bid |
/users/3/books/9 |
{ uid: "3", bid: "9" } |
/books/:id |
/books/ |
ไม่ตรง (ต้องมีค่าอยู่ตรงนั้น) |
| ปัญหา | สาเหตุ | วิธีแก้ |
|---|---|---|
| เทียบ id แล้วไม่เจอ | req.params.id เป็น string |
Number() ก่อนเสมอ |
ใช้ req.param.id (ไม่มี s) |
พิมพ์ผิด | ต้องเป็น req.params มี s |
/books/search ถูก :id ดักไป |
ลำดับ route | ย้าย route เจาะจงขึ้นบน |
| ตั้งชื่อ param ซ้ำกันใน route เดียว | /books/:id/:id |
ตัวหลังจะทับตัวหน้า — ตั้งชื่อให้ต่างกัน |
คาดว่า /books/ (ไม่มีค่า) จะเข้า /books/:id |
Express ต้องมีค่าอยู่จริง | ถ้าอยากให้ไม่บังคับใช้ /books/:id? (มี ?) |
ลืม validate แล้วโดนยิง /books/../../etc |
ไม่ตรวจ input | ตรวจชนิดข้อมูลก่อนใช้เสมอ |
req.params = ค่าที่ฝังอยู่ใน path ตามตำแหน่งของ :ชื่อ400, ไม่มีของตอบ 404
Workshop — เล่นกับ Route Parameter
เพิ่ม validation ให้ GET /books/:id
id ไม่ใช่จำนวนเต็ม (เช่น /books/abc, /books/1.5) → 400 พร้อมข้อความชัดเจนid เป็นตัวเลขแต่ไม่มีในระบบ → 404สร้าง GET /books/year/:year/author/:author
[]ทดสอบด้วย /books/year/1997/author/rowling
เพิ่ม console.log(req.params) ไว้ใน route แล้วยิงหลายๆ แบบ จดว่าได้อะไรบ้าง
| ยิงอะไร | req.params ได้อะไร |
|---|---|
/books/42 |
? |
/books/abc |
? |
/books/year/1997/author/rowling |
? |
คำถาม: ค่าที่ได้ทั้งหมดเป็นชนิดอะไร? พิสูจน์ด้วย typeof

ข้อ 1. ใน route "/users/:uid/books/:bid" ถ้ายิง /users/3/books/9 จะได้ req.params เป็นอะไร
ข้อ 2. Number.isInteger(Number("1.5")) ได้ค่าอะไร
ข้อ 3. ควรใช้ req.params เมื่อไหร่
ข้อ 4. /books/abc ควรตอบ 400 หรือ 404 และเพราะอะไร
ข้อ 5. req.param.id (ไม่มี s) จะเกิดอะไรขึ้น