Membangun REST API JSON Sederhana
Konsep REST, metode HTTP, kode status, routing manual dengan $_SERVER, membaca body JSON, respons JSON yang konsisten, validasi, dan menguji API dengan curl.
Apa itu REST API?
API adalah "pintu" tempat program lain (aplikasi mobile, front-end React, layanan lain) meminta atau mengirim data ke aplikasimu. REST adalah gaya merancang API di atas HTTP dengan aturan sederhana: sumber daya (resource) diberi alamat URL, dan metode HTTP menyatakan aksinya. Format data yang umum adalah JSON.
| Metode | URL | Aksi | Status sukses |
|---|---|---|---|
| GET | /tugas | Daftar semua tugas | 200 |
| GET | /tugas/5 | Satu tugas | 200 |
| POST | /tugas | Buat tugas baru | 201 |
| PUT / PATCH | /tugas/5 | Ubah tugas | 200 |
| DELETE | /tugas/5 | Hapus tugas | 204 |
Aturan penamaan: URL berupa kata benda jamak (/tugas), bukan kata kerja (/ambilSemuaTugas); aksi ditentukan oleh metode HTTP.
Kode status HTTP
| Kode | Arti | Kapan |
|---|---|---|
| 200 | OK | Berhasil mengambil/mengubah |
| 201 | Created | Berhasil membuat data baru |
| 204 | No Content | Berhasil, tanpa isi (hapus) |
| 400 | Bad Request | JSON rusak / permintaan tidak masuk akal |
| 401 / 403 | Unauthorized / Forbidden | Belum login / tidak punya hak |
| 404 | Not Found | Data atau URL tidak ada |
| 405 | Method Not Allowed | Metode tidak didukung |
| 422 | Unprocessable Content | Data gagal validasi |
| 500 | Server Error | Bug di sisi server |
Fungsi respons JSON
function kirimJson(mixed $data, int $status = 200): never
{
http_response_code($status);
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
Tipe kembalian never (PHP 8.1) berarti fungsi ini tidak pernah kembali ke pemanggil karena program berhenti di exit.
Membaca permintaan
$metode = $_SERVER['REQUEST_METHOD']; // GET, POST, ...
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); // /tugas/5
$segmen = explode('/', trim($path, '/')); // ['tugas', '5']
// Body JSON (bukan $_POST!)
$body = json_decode(file_get_contents('php://input'), true, flags: JSON_THROW_ON_ERROR);
$_POST hanya terisi untuk form biasa. Klien API biasanya mengirim JSON mentah, jadi bacalah dari php://input. Dengan JSON_THROW_ON_ERROR JSON rusak melempar JsonException yang bisa kamu ubah menjadi respons 400.
Routing sederhana
try {
$id = isset($segmen[1]) ? (int) $segmen[1] : null;
if ($segmen[0] !== 'tugas') {
kirimJson(['error' => 'Rute tidak ditemukan'], 404);
}
match (true) {
$metode === 'GET' && $id === null => kirimJson($repo->semua()),
$metode === 'GET' && $id !== null => kirimJson($repo->cari($id) ?? kirimJson(['error' => 'Tidak ditemukan'], 404)),
$metode === 'POST' && $id === null => buatTugas($repo),
default => kirimJson(['error' => 'Metode tidak didukung'], 405),
};
} catch (JsonException) {
kirimJson(['error' => 'JSON tidak valid'], 400);
}
Validasi dan respons error yang konsisten
function buatTugas(TugasRepository $repo): never
{
$body = json_decode(file_get_contents('php://input'), true, flags: JSON_THROW_ON_ERROR);
$judul = trim((string) ($body['judul'] ?? ''));
if ($judul === '') {
kirimJson(['error' => 'Validasi gagal', 'detail' => ['judul' => 'Judul wajib diisi']], 422);
}
$tugas = $repo->simpan($judul);
kirimJson($tugas, 201);
}
Pilih satu bentuk error dan pakai di mana-mana, misalnya {"error": "pesan", "detail": {...}}. Klien jadi mudah menanganinya.
Menjalankan dan mencoba
php -S localhost:8000 index.php
curl http://localhost:8000/tugas
curl -X POST http://localhost:8000/tugas \
-H "Content-Type: application/json" \
-d '{"judul":"Belajar REST"}'
curl -i http://localhost:8000/tugas/999 # -i menampilkan status 404
Praktik yang baik
- Selalu kirim
Content-Type: application/jsondan status yang tepat, bukan 200 untuk semuanya. - Jangan membocorkan pesan error internal (query SQL, path berkas) ke klien; catat ke log, kirim pesan umum dengan status 500.
- Validasi semua input; jangan percaya klien. Gunakan prepared statement untuk database.
- Pakai versi pada URL jika API akan berkembang:
/api/v1/tugas. - Amankan dengan token (header
Authorization: Bearer ...) dan batasi laju permintaan untuk API publik. Di proyek besar, pakai framework seperti Laravel yang sudah menyediakan routing, validasi, dan autentikasi.
Error umum
- Body kosong padahal klien mengirim JSON → membaca
$_POST, seharusnyaphp://input. Cannot modify header information - headers already sent→ ada output (spasi/echo) sebelumheader(). Panggil header dulu, dan jangan menutup berkas dengan?>.- JSON tampil sebagai teks di browser tanpa format → lupa header
Content-Type.