สร้าง JSON API ที่รัดกุมด้วยการเชี่ยวชาญเรื่องเฮดเดอร์ การอ่านเนื้อหาดิบ (raw body) และความหมายที่ละเอียดอ่อนของรหัสสถานะ
เปิดบทเรียนนี้ใน KodokonJSON API คือสัญญาข้อตกลง ทุกการตอบสนองจะประกาศชนิดของมัน (Content-Type: application/json) พร้อมรหัสสถานะที่ถูกต้องและโครงสร้างที่คงที่ PHP ไม่ส่งสิ่งเหล่านี้เลยตามค่าเริ่มต้น มันประกาศเป็น text/html บล็อกแรกที่จะสร้างคือ ตัวช่วยตอบสนอง (response helper) เพียงตัวเดียว ที่มีชนิดเป็น never (PHP 8.1 ขึ้นไป) ชนิดที่คืนค่านี้รับประกันทั้งต่อเอนจินและต่อเครื่องมือวิเคราะห์แบบสถิตว่าฟังก์ชันจะไม่มีวันคืนการควบคุมกลับมา โค้ดใด ๆ ที่เขียนหลังการเรียกจึงพิสูจน์ได้ว่าไปไม่ถึง
<?php
declare(strict_types=1);
function jsonResponse(
mixed $data,
int $status = 200
): never {
http_response_code($status);
header('Content-Type: application/json');
echo json_encode(
$data,
JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE
);
exit;
}
jsonResponse(['status' => 'ok']);ความละเอียดอ่อนข้อที่สอง ซึ่งมักถูกค้นพบเมื่อสายเกินไป $_POST จะ ว่างเปล่า เมื่อเจอกับเนื้อหาแบบ JSON PHP จะเติมมันให้เฉพาะสำหรับ application/x-www-form-urlencoded และ multipart/form-data เท่านั้น เนื้อหาดิบถูกอ่านจากสตรีม php://input ให้ถอดรหัสมันด้วย JSON_THROW_ON_ERROR หากไม่มีแฟล็กนั้น json_decode จะคืนค่า null แบบเงียบ ๆ เมื่อเกิดข้อผิดพลาด ซึ่งแยกไม่ออกจากเนื้อหาที่มีคำว่า null อยู่จริง ๆ และด้วยชนิด never คำสั่ง switch ด้านล่างจึงไม่ต้องมี break เลยแม้แต่น้อย
<?php
declare(strict_types=1);
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
jsonResponse(['items' => []]);
case 'POST':
$raw = (string) file_get_contents(
'php://input'
);
try {
$payload = json_decode(
$raw,
true,
512,
JSON_THROW_ON_ERROR
);
} catch (JsonException) {
jsonResponse(
['error' => 'Malformed JSON'],
400
);
}
header('Location: /items/42');
jsonResponse(['created' => $payload], 201);
default:
header('Allow: GET, POST');
jsonResponse(
['error' => 'Method not allowed'],
405
);
}จงเลือกรหัสอย่างแม่นยำ เพราะไคลเอนต์ของคุณจะเขียนโปรแกรมโดยอิงกับรหัสเหล่านั้น ไม่ใช่กับข้อความของคุณ 200 อ่านสำเร็จ, 201 การสร้าง (พร้อมเฮดเดอร์ Location ที่ชี้ไปยังทรัพยากร), 204 สำเร็จโดยไม่มีเนื้อหา, 400 JSON ผิดรูปแบบ, 404 ไม่พบทรัพยากร, 405 เมท็อดที่ไม่รองรับ (พร้อมเฮดเดอร์ Allow ที่ระบุเมท็อดที่อนุญาต) และ 422 สำหรับ JSON ที่ถูกต้องตามไวยากรณ์แต่ผิดในเชิงความหมาย ตรวจสอบทั้งหมดด้วย curl -i ซึ่งจะแสดงเฮดเดอร์ที่ได้รับ
curl -i -X POST http://localhost:8000/items \
-H 'Content-Type: application/json' \
-d '{"name":"Widget"}'