Sejauh ini aplikasi PHP yang kita bangun berbicara kepada manusia — lewat halaman HTML di browser atau teks di terminal. Section ini membuka pintu yang berbeda: program kita yang berbicara kepada program lain. Aplikasi mobile meminta daftar tugas, layanan pembayaran menagih status pesanan, skrip cron mengambil laporan harian — semuanya lewat HTTP, dan REST adalah gaya arsitektur yang paling umum dipakai untuk merancang percakapan tersebut. Sebelum menyentuh routing atau JSON, kita perlu memahami dulu apa sebenarnya REST itu, apa yang dijanjikannya, dan kesalahpahaman apa yang paling sering menempel padanya — karena fondasi konseptual yang goyah akan terasa di setiap endpoint yang kita rancang.
REST Adalah Gaya Arsitektur, Bukan Protokol #
REST (Representational State Transfer) lahir dari disertasi Roy Fielding tahun 2000 — salah satu penulis utama spesifikasi HTTP — sebagai cara berpikir tentang bagaimana sistem terdistribusi seharusnya memanfaatkan HTTP, bukan sekadar menumpang di atasnya. Karena itulah REST tidak pernah menjadi protokol atau standar: tidak ada badan yang mengeluarkan sertifikat kepatuhan, tidak ada spesifikasi normatif yang bisa di-checklist satu per satu. REST adalah kumpulan constraint — aturan desain seperti statelessness dan antarmuka seragam — yang bila diikuti, memberi sistem properti yang diidamkan: kesederhanaan, kemampuan di-cache, dan kemudahan penskalaan.
Bukti terbaik bahwa gaya ini bekerja adalah web itu sendiri. Aktivitas membuka halaman, mengeklik tautan, menekan tombol back — semuanya sudah menjalankan prinsip REST selama puluhan tahun, jauh sebelum para programmer mendeskripsikan API mereka sebagai “RESTful”. Ketika kita merancang REST API, pada dasarnya kita meminjam cara kerja web yang sudah terbukti itu dan menerapkannya untuk data yang dikonsumsi program. Pemahaman ini penting karena menjelaskan mengapa REST terasa “alami” untuk HTTP, dan mengapa memaksakan kebiasaan lain — misalnya memperlakukan HTTP sebagai pipa dummy tempat semua perintah dikirim — akan membuang seluruh keunggulannya.
Tiga Kata Kunci: Resource, Verb, Representasi #
Seluruh cara berpikir REST bisa diringkas menjadi tiga pertanyaan. Pertama, apa yang tersedia? Jawabannya adalah resource — setiap “benda” yang layak punya identitas: satu tugas, kumpulan tugas, satu pengguna, satu laporan. Kedua, apa yang dilakukan terhadapnya? Jawabannya bukan nama fungsi di URL, melainkan HTTP verb — GET, POST, PUT, PATCH, DELETE — yang menjadi kosakata aksi yang seragam untuk semua resource. Ketiga, dalam bentuk apa resource dikirim? Jawabannya adalah representasi — snapshot data pada satu momen, biasanya berformat JSON saat ini, meski XML, HTML, atau CSV sama-sama sah.
Pemisahan ketiganya adalah sumber kekuatan REST. Resource dan representasi dipisahkan agar satu benda yang sama bisa tampil dalam wujud berbeda untuk pemanggil yang berbeda; verb dan resource dipisahkan agar satu URL yang sama (/tugas/42) mendukung banyak aksi hanya dengan berganti method. Perhatikan betapa berbedanya ini dari kebiasaan lama yang memakukan semuanya menjadi satu nama prosedur:
| Kebiasaan RPC | Padanan REST | Yang berubah |
|---|---|---|
POST /api/ambilDaftarTugas | GET /tugas | aksi menjadi verb bawaan HTTP |
POST /api/buatTugas | POST /tugas | verb sama, URL kini menunjuk koleksi |
POST /api/updateTugas?id=42 | PATCH /tugas/42 | identitas pindah ke path, bukan parameter |
POST /api/hapusTugas?id=42 | DELETE /tugas/42 | tidak butuh kata “hapus” di mana-mana |
Pola di kolom kiri adalah gaya RPC (Remote Procedure Call): HTTP direduksi menjadi kurir yang mengantar nama fungsi. Pola di kolom kanan memperlakukan URL sebagai benda dan method sebagai kata kerja — kalimatnya terbaca GET /tugas sebagai “ambil koleksi tugas”. Pergeseran sudut pandang inilah yang disebut URL-as-resource thinking, dan inilah perbedaan pertama yang paling terasa saat membaca API yang dirancang dengan REST.
Representasi: Satu Resource, Banyak Wujud #
Representasi adalah jawaban atas pertanyaan “bagaimana bentuk data saat dikirim”. Dalam PHP, bentuk paling umum saat ini adalah JSON yang dihasilkan json_encode():
<?php
$tugas = [
'id' => 42,
'judul' => 'Menulis dokumentasi API',
'status' => 'todo',
'penerima' => '[email protected]',
];
echo json_encode($tugas, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), "\n";Output yang Dihasilkan:
{
"id": 42,
"judul": "Menulis dokumentasi API",
"status": "todo",
"penerima": "[email protected]"
}Array PHP diterjemahkan menjadi objek JSON, dan flag JSON_UNESCAPED_UNICODE menjaga teks kita tetap terbaca manusia. Perlu dipegang satu disiplin pikiran: JSON ini bukan tugasnya, melainkan foto tugas pada satu momen — representasinya. Tugas yang sama bisa saja tersaji dalam format lain untuk pemanggil lain. Fungsi kecil berikut memperlihatkan ide itu dalam skala mini:
<?php
function renderTugas(array $tugas, string $format): string
{
return match ($format) {
'json' => json_encode($tugas, JSON_UNESCAPED_UNICODE),
'teks' => "#{$tugas['id']} [{$tugas['status']}] {$tugas['judul']}",
default => throw new InvalidArgumentException("format tidak didukung: $format"),
};
}
$tugas = [
'id' => 42,
'judul' => 'Menulis dokumentasi API',
'status' => 'todo',
];
echo renderTugas($tugas, 'json'), "\n";
echo renderTugas($tugas, 'teks'), "\n";Output yang Dihasilkan:
{"id":42,"judul":"Menulis dokumentasi API","status":"todo"}
#42 [todo] Menulis dokumentasi APISatu resource, dua representasi: renderTugas() mengembalikan JSON untuk pemanggil program dan teks ringkas untuk laporan CLI, tanpa resource-nya berubah. Di dunia HTTP, pemilihan wujud ini biasanya dinegosiasikan lewat header Accept yang dikirim klien — mekanisme yang dikenal sebagai content negotiation — dan kita akan mempraktikkannya saat menyusun respons JSON pada chapter berikutnya. Konsekuensi praktisnya untuk perancangan: jangan pernah menaruh detail format ke dalam URL seperti /tugas/42.json kecuali ada alasan kuat, karena URL adalah identitas resource yang seharusnya netral terhadap wujudnya.
HTTP Verb sebagai Antarmuka Aksi #
Kosakata verb HTTP kecil — hanya lima method yang dipakai sehari-hari — dan justru kecilnya yang membuatnya kuat sebagai antarmuka seragam. Tabel berikut merangkum makna, keamanan, dan idempotensinya; dua istilah terakhir akan kita bedah tuntas di chapter idempotency :
| Method | Makna terhadap resource | Aman | Idempoten |
|---|---|---|---|
GET | membaca representasi, tanpa efek samping | ya | ya |
POST | membuat anggota baru di koleksi / memproses | tidak | tidak |
PUT | mengganti representasi secara utuh | tidak | ya |
PATCH | mengubah sebagian field | tidak | umumnya tidak |
DELETE | menghapus resource | tidak | ya |
Dua properti di kolom kanan bukan hiasan tabel. Aman (GET) memberi izin kepada semua lapisan di antara klien dan server — proxy, browser, CDN — untuk melakukan caching, prefetching, dan bookmarking tanpa takut mengubah keadaan. Idempoten memberi jaminan bahwa pemanggilan ulang setelah kegagalan jaringan tidak menduplikasi efeknya — DELETE /tugas/42 yang dikirim dua kali tetap meninggalkan satu keadaan akhir. Ketika rancangan kita menghormati makna method, seluruh infrastruktur web ikut bekerja untuk kita secara gratis; ketika kita melanggarnya — misalnya GET yang ternyata mengubah data — kita merusat kontrak yang paling mendasar.
Statelessness: Setiap Request Berdiri Sendiri #
Constraint REST yang paling sering disalahpahami adalah statelessness: server tidak boleh mengingat keadaan percakapan di antara request. Setiap request harus membawa seluruh informasi yang dibutuhkan untuk dipahami — kredensial di header, identifikasi resource di path, parameter halaman di query string. Server boleh menyimpan resource (itulah tugasnya), tetapi tidak boleh menyimpan konteks sesi yang membuat request berikutnya bergantung pada request sebelumnya.
Mari kita lihat wujudnya dalam HTTP sungguhan. Kode berikut adalah router mini untuk server bawaan PHP yang menyajikan satu resource tugas — kita jalankan dengan php -S, lalu jajal dengan curl:
<?php
// router-api.php — server demo untuk menjajal REST lewat HTTP
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if ($_SERVER['REQUEST_METHOD'] === 'GET' && $path === '/tugas/42') {
header('Content-Type: application/json');
echo json_encode([
'id' => 42,
'judul' => 'Menulis dokumentasi API',
'status' => 'todo',
]);
return true;
}
http_response_code(404);
header('Content-Type: application/json');
echo json_encode(['error' => 'resource tidak ditemukan']);php -S 127.0.0.1:8099 router-api.phpDari terminal kedua, kita minta resource yang ada dan resource yang tidak ada:
curl -i http://127.0.0.1:8099/tugas/42
curl -i http://127.0.0.1:8099/tugas/999Berikut transkrip aslinya — dua request yang sama sekali tidak mengandung cookie, session, maupun memori percakapan sebelumnya:
$ curl -i http://127.0.0.1:8099/tugas/42
HTTP/1.1 200 OK
Host: 127.0.0.1:8099
Date: Tue, 13 Oct 2026 15:13:55 GMT
Connection: close
X-Powered-By: PHP/8.4.23
Content-Type: application/json
{"id":42,"judul":"Menulis dokumentasi API","status":"todo"}
$ curl -i http://127.0.0.1:8099/tugas/999
HTTP/1.1 404 Not Found
Host: 127.0.0.1:8099
Date: Tue, 13 Oct 2026 15:13:55 GMT
Connection: close
X-Powered-By: PHP/8.4.23
Content-Type: application/json
{"error":"resource tidak ditemukan"}Mari kita baca transkrip tersebut baris demi baris. Baris pertama adalah status line: HTTP/1.1 200 OK menyatakan protokol, kode status, dan alasan — kode 200 berarti resource ditemukan dan representasinya menyusul, sedangkan 404 berarti identitas yang diminta tidak ada. Baris-baris berikutnya adalah header: Content-Type: application/json memberi tahu pemanggil format representasinya, sementara Date dan X-Powered-By ditambahkan oleh server. Setelah baris kosong, body membawa representasi — JSON untuk kasus sukses, pesan error yang juga berformat JSON untuk kegagalan. Seluruh makna request terletak pada GET + path; ulangi request itu kapan pun, dari mesin mana pun, hasilnya sama — itulah statelessness dalam praktik.
Manfaat statelessness baru terasa saat sistem bertumbuh. Karena tidak ada keadaan percakapan yang menempel di satu server, load balancer bebas mengarahkan request ke mesin mana pun yang sedang kosong, dan server yang jatuh cukup diganti tanpa memindahkan “sesi” apa pun. Harganya pun jujur: state yang memang perlu — siapa pengguna, di halaman mana — harus digendong request itu sendiri, biasanya dalam bentuk token. Di sisi PHP, ini berarti kita bergerak menjauh dari $_SESSION sebagaimana kita kenal, dan lebih banyak bekerja dengan header serta token yang divalidasi setiap request.
Richardson Maturity Model #
Seberapa jauh sebuah API “menjadi REST”? Leonard Richardson memetakan jalannya ke dalam empat tingkat yang kini dikenal sebagai Richardson Maturity Model — alat yang paling enak dipakai bukan untuk memenangkan perdebatan, melainkan untuk menilai posisi API kita sendiri:
| Level | Nama | Ciri utama | Contoh |
|---|---|---|---|
| 0 | HTTP sebagai terowongan | satu endpoint, semua operasi lewat POST | POST /api dengan body {"aksi": "ambilTugas"} |
| 1 | Resource | URL mulai menunjuk benda, method masih seragam | POST /tugas/42/hapus |
| 2 | Verb dan status code | HTTP dipakai penuh: method bermakna, respons berkode | DELETE /tugas/42 mengembalikan 204 |
| 3 | HATEOAS | respons menyertakan tautan tindak lanjut | body memuat "links" ke operasi berikutnya |
Perjalanan dari level 0 ke 2 adalah bagian yang memberi imbal balik paling besar: API menjadi bisa di-cache, di-load-balance, dan dibaca tanpa dokumen tebal karena method dan status code sudah bermakna. Level 3 — HATEOAS, singkatan dari Hypermedia as the Engine of Application State — adalah wujud REST yang paling murni menurut Fielding: klien menemukan tindakan berikutnya dari tautan yang disajikan server, seperti manusia mengeklik tautan di halaman web. Level ini jarang dikejar penuh di dunia nyata karena menuntut disiplin klien yang tinggi, dan kebanyakan API publik yang sukses berhenti nyaman di level 2.
Miskonsepsi Umum tentang REST #
Karena REST lebih sering didengar daripada dipahami, beberapa mitos tumbuh subur. Mitos pertama: “REST artinya API yang mengembalikan JSON”. JSON hanyalah representasi yang sedang populer — REST berumur lebih tua dari JSON sebagai format umum, dan API yang menyajikan XML atau HTML bisa justru lebih patuh pada gaya REST daripada API JSON yang menumpang semua operasi pada satu POST. Mitos kedua: “REST artinya URL yang cantik”. Kerapihan URL adalah level 1 Richardson — penting, tetapi kalau semua tetangannya masih POST dan semua responsnya 200 dengan pesan error di dalam body, arsitekturnya belum bergerak.
Mitos ketiga agak lebih halus: “REST dan RPC adalah musuh yang tidak bisa didamaikan”. Kenyataannya keduanya menyelesaikan masalah yang mirip dengan filosofi berbeda — RPC mengoptimalkan untuk pemanggil yang ingin memanggil fungsi jarak jauh seolah lokal, sementara REST mengoptimalkan untuk sistem yang tumbuh di atas infrastruktur web. Banyak API nyata adalah campuran yang sadar: kerangka resource untuk operasi data, plus beberapa endpoint bertindak yang jujur diakui sebagai RPC. Yang merugikan bukan campuran itu, melainkan mengklaim sesuatu REST tanpa memberikan manfaat yang dijanjikan REST.
Ringkasan #
REST adalah gaya arsitektur yang meminjam cara kerja web: resource sebagai benda beridentitas URL, HTTP verb sebagai kosakata aksi yang seragam, representasi yang terpisah dari identitas, dan statelessness yang membuat setiap request berdiri sendiri. Model Richardson memberi kita peta untuk menilai seberapa jauh sebuah API menghidupi gaya tersebut, dan kesadaran bahwa berhenti di level 2 adalah pilihan yang sah. Pertanyaan desain pertama yang menanti bukan lagi “apa itu REST”, melainkan “resource apa saja yang hidup di domain kita, dan bagaimana wujud URL terbaiknya” — pertanyaan yang kita jawab tuntas pada chapter berikutnya tentang resource modeling.