Perbedaan GET dan POST di PHP

| | PHP
Perbedaan GET dan POST di PHP

GET dan POST itu dua method HTTP yang paling sering dipakai buat ngirim data dari form HTML ke server. dua-duanya ngirim data, tapi cara kerja, keamanan, dan kegunaannya beda jauh. kalau kalian baru mulai bikin form, paham dulu cara membuat form di HTML dan PHP biar artikel ini langsung nyambung.

aturan praktis yang selalu saya pegang dan terbukti sampai sekarang: GET untuk mencari, POST untuk mengubah. form pencarian dan filter pakai GET supaya URL-nya bisa dibagikan, sedangkan form login, tambah, edit, hapus pakai POST karena mengubah data di server. kalau kalian ingat satu kalimat ini, 90% keputusan sudah benar.

menurut saya, bingung di awal itu wajar, dulu saya juga pernah pakai GET buat form login karena kelihatan lebih simpel, baru sadar setelah password nongol di address bar dan kesimpan di history.

Kenapa Harus Beda? Soal Safe dan Idempotent

jika kalian baca RFC 9110 (HTTP Semantics), GET itu termasuk method yang safe dan idempotent, POST tidak.

maksudnya gini, safe itu tidak mengubah data di server, cuma baca aja. idempotent itu mau dipanggil sekali atau sepuluh kali hasilnya sama di server, tidak bikin efek ganda. makanya browser berani cache hasil GET, berani bookmark, dan tidak ngasih warning kalau kalian refresh. kalau POST di-refresh, browser pasti nanya dulu “mau kirim ulang?” karena POST bisa bikin data dobel, misal transaksi kepencet dua kali.

jadi bukan cuma soal PHP, ini aturan HTTP-nya memang begitu.

1. Method GET, Data yang Nempel di URL

data GET dikirim lewat URL (query string):

<!-- Form GET -->
<form method="GET" action="cari.php">
    <input type="text" name="q">
    <button type="submit">Cari</button>
</form>

saat disubmit, URL jadi:

cari.php?q=belajar+php

di PHP, data diambil dari $_GET:

<?php
$keyword = $_GET['q'] ?? '';
echo "Mencari: " . htmlspecialchars($keyword);

operator ?? di sini biar aman, kalau key q tidak ada, $keyword diisi string kosong, tidak muncul warning Undefined array key. saya biasakan tambah htmlspecialchars juga, biar kalau ada yang iseng masukin <script> tidak langsung ke-render di halaman.

catatan penting soal limit GET, secara teori HTTP tidak membatasi panjang URL, tapi praktisnya dibatasi browser dan server. Internet Explorer mentok sekitar 2083 karakter, Chrome dan Firefox modern kuat sampai 8000 an, Apache default LimitRequestLine 8190 bytes, Nginx 8k. kalau kalian pakai suhosin patch yang lama, $_GET bahkan dibatasi 512 karakter per parameter. jadi saran aman, jangan pakai GET untuk data panjang, kalau URL-nya sudah lebih dari 2000 karakter, itu tanda kalian harus pindah ke POST.

satu lagi yang sering kelewat, walaupun form kalian method="POST", kalau action-nya action="cari.php?q=php", nilai q itu tetap masuk ke $_GET, tidak hilang. jadi GET dan POST bisa muncul barengan di satu request.

2. Method POST, Data yang Ngumpet di Body

data POST dikirim lewat body request, tidak kelihatan di URL:

<!-- Form POST -->
<form method="POST" action="login.php">
    <input type="text" name="username">
    <input type="password" name="password">
    <button type="submit">Login</button>
</form>

di PHP, data diambil dari $_POST:

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = $_POST['username'] ?? '';
    $password = $_POST['password'] ?? '';
}

cek $_SERVER['REQUEST_METHOD'] dulu itu kebiasaan bagus menurut saya, biar jelas kalian memang lagi handle POST, bukan GET yang nyasar.

limit POST tidak lewat URL, tapi lewat setting PHP. default post_max_size = 8M, upload_max_filesize = 2M, dan max_input_vars = 1000 (jumlah maksimal variabel input, berlaku terpisah untuk GET, POST, dan COOKIE). kalau melebihi post_max_size, $_POST bisa kosong total tanpa error yang jelas, jadi kalau form tiba-tiba tidak kekirim padahal data besar, cek php.ini dulu.

untuk upload file, POST wajib pakai enctype="multipart/form-data":

<form method="POST" enctype="multipart/form-data" action="upload.php">
    <input type="file" name="foto">
    <button>Upload</button>
</form>

tanpa enctype itu, file tidak akan masuk ke $_FILES.

3. Perbandingan Langsung

biar gampang milih, ini tabel perbandingannya yang sudah saya sesuaikan dengan kondisi real di browser dan server:

AspekGETPOST
Data dikirim viaURL (query string)Body request
Terlihat di URLYa, jelas di address barTidak
Bisa di-bookmark dan shareYaTidak
Limit ukuranpraktis <2000 karakter aman, maksimal tergantung browser/server (IE 2083, Apache 8190)tergantung post_max_size (default 8M) dan max_input_vars (1000)
CacheYa, bisa di-cache browser dan CDNTidak di-cache secara default
Idempotent dan Safe (RFC 9110)Ya, safe dan idempotentTidak
History browserYa, tersimpan lengkapTidak simpan parameter, tapi browser minta konfirmasi saat refresh
Kelihatan di log server dan RefererYa, URL lengkap kecatat di access log dan bisa kebawa di header RefererTidak di URL, tapi tetap kelihatan di DevTools tab Network
Tipe dataHanya teks url-encodedTeks, file, JSON, bisa multipart/form-data
PenggunaanPencarian, filter, sorting, paginationLogin, tambah, edit, hapus, upload

4. Kelebihan GET

  • URL bisa di-bookmark dan dibagikan, enak buat kolaborasi
  • request bisa di-cache, jadi lebih cepat buat halaman publik
  • cocok untuk filter yang hasilnya perlu di-share
// Contoh: form pencarian, cocok pakai GET
<form method="GET" action="produk.php">
    <input name="kategori" placeholder="Kategori">
    <input name="min_harga" placeholder="Harga min">
    <input name="max_harga" placeholder="Harga max">
    <button>Cari</button>
</form>
// URL: produk.php?kategori=laptop&min_harga=5000000

bayangin pengalaman user-nya: hasil filter bisa dikirim ke teman lewat link, dan URL-nya langsung kebaca, itu keunggulan utama GET yang tidak bisa diganti POST.

5. Kelebihan POST

  • data tidak nongol di URL, jadi tidak ke-share tidak sengaja
  • bisa ngirim data panjang dan kompleks
  • mendukung upload file
  • tidak numpuk di history dan tidak kecache sembarangan
// Contoh: form login, WAJIB pakai POST
<form method="POST" action="login.php">
    <input type="text" name="username" required>
    <input type="password" name="password" required>
    <button>Login</button>
</form>

jangan khawatir POST terlihat lebih ribet, sebenarnya sama aja, cuma beda tempat ngirimnya.

6. $_REQUEST, Gabungan GET + POST + Cookie

PHP juga nyediain $_REQUEST yang menggabungkan GET, POST, dan COOKIE:

// Bisa menerima data dari GET atau POST, tapi jangan dipakai
$nama = $_REQUEST['nama'] ?? '';

urutan gabungnya diatur di php.ini lewat variables_order dan request_order, default-nya GPCS (GET, POST, COOKIE, SERVER). artinya kalau ada nama yang sama di GET dan POST, yang menang tergantung konfigurasi server, tidak konsisten.

catatan dari saya, hindari $_REQUEST untuk form biasa. pakai $_GET atau $_POST secara spesifik, biar jelas asal datanya dan tidak rentan konflik nama. $_REQUEST juga bikin token CSRF kalau ditaruh di URL jadi bocor lewat log, dan OWASP sendiri menyarankan jangan kirim token lewat GET.

kalau mau lebih aman dan eksplisit, pakai filter_input:

$q = filter_input(INPUT_GET, 'q', FILTER_SANITIZE_SPECIAL_CHARS);

7. Keamanan: Mengapa POST Bukan Solusi Ajaib

POST ngirim data di body, bukan berarti data aman. ini pelajaran yang saya pelajari dengan cara yang cukup keras: dulu saya mengira kalau pakai POST data aman, sampai saya membuka DevTools browser saya sendiri di tab Network dan melihat data form yang terkirim jelas terpampang di sana.

jadi data POST tetap:

  • masih bisa dicegat kalau tidak pakai HTTPS (ini wajib, baca juga perbedaan HTTP dan HTTPS)
  • masih bisa dilihat lewat browser DevTools di tab Network, jadi jangan anggap POST itu enkripsi
  • masih kecatat kalau kalian log body request di server
  • tidak terlindungi dari CSRF tanpa token

beda dengan GET, data GET itu lebih bocor lagi karena muncul di banyak tempat: history browser, bookmark, access log server, bahkan header Referer kalau user klik link ke situs lain. makanya password, token, atau data sensitif jangan pernah pakai GET, walau sudah HTTPS sekalipun.

solusinya bukan cuma ganti method, tapi tambah proteksi:

// ❌ Hanya POST saja tidak cukup
<form method="POST" action="hapus.php">
    <input type="hidden" name="id" value="1">
    <button>Hapus</button>
</form>

// ✅ Tambahkan CSRF token yang divalidasi di server
<?php
session_start();
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>
<form method="POST" action="hapus.php">
    <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
    <input type="hidden" name="id" value="1">
    <button>Hapus</button>
</form>

<?php
// di hapus.php
session_start();
if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf_token'] ?? '')) {
    http_response_code(403);
    die('CSRF token tidak valid');
}
// baru proses hapus

ide CSRF token-nya gini, server ngegenerate token acak per session, form ikut ngirim token itu, lalu server ngecek pakai hash_equals. kalau token tidak cocok, request ditolak. ini ngehalau serangan dari situs lain yang nyoba maksa browser kalian submit form diam-diam. dan ingat, token jangan pernah dikirim lewat GET atau URL, karena bakal bocor di log dan history.

8. Studi Kasus: Filter Produk + Keranjang

<!-- Filter (GET), bisa dibookmark -->
<form method="GET">
    <select name="kategori">
        <option value="laptop">Laptop</option>
        <option value="hp">HP</option>
    </select>
    <input type="range" name="max_harga" min="0" max="20000000">
    <button>Filter</button>
</form>

<!-- Keranjang (POST), mengubah data -->
<form method="POST" action="tambah-keranjang.php">
    <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token'] ?? '') ?>">
    <input type="hidden" name="produk_id" value="123">
    <input type="number" name="jumlah" value="1">
    <button>Tambah ke Keranjang</button>
</form>

perhatikan polanya: filter pakai GET karena cuma melihat data dan hasilnya berguna kalau dibagikan, sedangkan tombol tambah ke keranjang pakai POST karena dia mengubah isi keranjang di server. satu halaman, dua method, dua alasan yang beda. kalau ketuker, misal tambah keranjang pakai GET, orang bisa iseng share link tambah-keranjang.php?produk_id=123 dan tiap yang klik langsung nambah barang tanpa sadar.

9. Tips Aman yang Selalu Saya Pakai di PHP

jika sudah paham bedanya, ini checklist kecil biar form kalian tidak gampang jebol:

  • cek method dulu, if ($_SERVER['REQUEST_METHOD'] !== 'POST') tolak langsung
  • sanitasi output pakai htmlspecialchars saat echo balik ke HTML
  • validasi input, jangan percaya $_GET atau $_POST mentah-mentah
  • pakai HTTPS untuk semua form, terutama login
  • untuk aksi yang mengubah data (login, hapus, transfer), wajib POST plus CSRF token

Kesimpulan

gunakan GET ketika:

  • pencarian, filter, sorting, pagination, URL-nya perlu dibagikan
  • tidak mengubah data di server (safe dan idempotent)
  • data pendek dan tidak sensitif

gunakan POST ketika:

  • login dan registrasi, data sensitif
  • mengubah data (tambah, edit, hapus)
  • upload file, pakai multipart/form-data
  • data panjang atau kompleks

kalau masih ragu, balik lagi ke kalimat awal: GET untuk mencari, POST untuk mengubah. pegang itu, kalian sudah aman di 90% kasus.

Baca Juga Mengenai :


Pertanyaan yang Sering Diajukan

Apa bedanya GET dan POST di PHP?

GET ngirim data lewat URL (query string) dan bisa di-bookmark, cocok buat pencarian. POST ngirim data lewat body request, tidak tampak di URL, cocok buat login dan data sensitif.

Kapan pakai GET dan kapan pakai POST?

aturan praktisnya, GET untuk mencari (pencarian, filter, sorting), POST untuk mengubah (login, tambah, edit, hapus). data yang mengubah kondisi server sebaiknya lewat POST.

Apakah POST lebih aman dari GET?

POST memang tidak menampilkan data di URL, tapi bukan berarti aman. data POST tetap bisa dilihat lewat DevTools browser, jadi tetap wajib HTTPS dan CSRF token untuk form yang mengubah data.

Apa itu $_REQUEST di PHP?

$_REQUEST itu variabel superglobal yang menggabungkan data dari $_GET, $_POST, dan $_COOKIE. sebaiknya hindari dan pakai $_GET atau $_POST secara spesifik biar jelas asal datanya.

Sigit Nurhanafi avatar
Full-stack developer & technical writer. Berpengalaman di PHP, Laravel, NodeJS, MySQL, dan Python. Aktif menulis tutorial pemrograman dan maintaining open-source projects di PemburuKode sejak 2021.