Form PHP mengirim data kembali ke script yang mencetaknya: tulis <form method="post"> dengan input yang diberi nama, dan saat $_SERVER['REQUEST_METHOD'] bernilai 'POST', baca setiap field sebagai $_POST['name']. Escape apa pun yang kamu cetak kembali dengan htmlspecialchars().
Jalankan blok ini, ketik sebuah nama ke form, lalu tekan Send: script yang sama berjalan lagi, kali ini dengan $_POST yang sudah terisi.
Ada tiga hal yang terjadi di sini dan dibutuhkan oleh setiap pemroses form:
- Pemeriksaan method. Pada kunjungan pertama, request-nya adalah GET dan belum ada yang perlu diproses.
?? 'GET'hanya berpengaruh saat file dijalankan dari command line, tempatREQUEST_METHODtidak diisi; di web server nilainya selalu ada. ?? ''di setiap field. Sebuah field bisa saja tidak ada (input yang namanya diganti, request yang dikirim oleh script), dan membaca key yang tidak ada akan mencetak warning.- Escaping saat output. Nama itu dimasukkan kembali ke halaman dua kali, dan
htmlspecialchars()memastikan nilai seperti<b>Ada</b>ditampilkan sebagai teks, bukan menjadi markup. Detailnya ada di halaman htmlspecialchars.
Validasi form dan tampilkan error di samping field
Kumpulkan error dalam array dengan nama field sebagai key. Jika array-nya kosong, form-nya valid; jika tidak, cetak form lagi dengan setiap pesan di bawah field-nya dan isian pengunjung tetap di tempatnya. Kirim form dalam keadaan kosong, lalu dengan email yang salah, lalu dengan nilai yang valid.
novalidate mematikan pemeriksaan bawaan browser agar kamu bisa melihat pemeriksaan PHP bekerja. Di form sungguhan, pakai keduanya: validasi browser adalah kemudahan untuk pengunjung, sedangkan validasi PHP-lah yang menentukan, karena siapa pun bisa mengirim request tanpa melewati form-mu. filter_var() menangani email dan rentang integer masing-masing dalam satu panggilan; halaman filter_var membahas filter lainnya.
Checkbox, radio button, dan select
Field teks selalu mengirim nilai, meskipun kosong. Kontrol lainnya tidak:
- Checkbox yang tidak dicentang sama sekali tidak mengirim apa pun, jadi key-nya tidak ada di
$_POST. - Checkbox bernama
topics[]datang sebagai array:$_POST['topics']berisi['php', 'sql']. - Grup radio atau
<select>mengirimvaluedari option yang dipilih.
Untuk menjaga pilihan setelah submit, cetak checked atau selected pada option yang cocok. Centang beberapa kotak, pilih level, lalu tekan Save.
Dua pemeriksaan setelah membaca input itu lebih penting daripada kelihatannya. array_intersect() membuang topik yang tidak ada di daftarmu, dan pemeriksaan is_string() ditambah array_key_exists() mengembalikan level ke nilai default jika seseorang mengirim nilai yang tidak pernah kamu tawarkan (atau sebuah array, yang akan membuat $levels[$level] melempar error). Select membatasi apa yang bisa dikirim browser, bukan apa yang bisa dimuat sebuah request.
Form multi-langkah dengan hidden field
Hidden input membawa sebuah nilai dari satu langkah ke langkah berikutnya tanpa menampilkannya. Di sini langkah 1 menanyakan nama, langkah 2 menanyakan bahasa dan ikut mengirim nama lewat hidden field, dan langkah 3 menampilkan keduanya. Lalui ketiga langkahnya.
Hidden field terlihat di source halaman dan bisa diubah seperti field lain, jadi aman dipakai untuk membawa jawaban pengunjung sendiri antarlangkah, tetapi jangan pernah untuk harga, id pengguna, atau role. Simpan data seperti itu di server, dalam session; lihat session dan cookie.
Post/Redirect/Get: hentikan pengiriman ulang saat refresh
Setelah POST berhasil, jika script langsung mencetak halaman "terima kasih", menekan refresh membuat browser mengirim POST itu lagi, dan pesanan atau komentarnya tersimpan dua kali. Solusinya adalah menyimpan, melakukan redirect, lalu menampilkan hasilnya lewat GET:
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$errors = validate($_POST);
if (!$errors) {
save_comment($_POST);
$_SESSION['flash'] = 'Comment posted.';
header('Location: /comments.php', true, 303);
exit;
}
// On errors, fall through and print the form with the messages.
}
$flash = $_SESSION['flash'] ?? null;
unset($_SESSION['flash']);
303 See Other memberi tahu browser untuk mengikuti redirect dengan GET. exit setelah header() itu penting: tanpanya, sisa script tetap berjalan. Redirect juga harus terjadi sebelum ada output apa pun, kalau tidak PHP menolak dengan "headers already sent".
Form sungguhan juga menambahkan token CSRF: nilai acak yang disimpan di session dan di hidden field, lalu dibandingkan dengan hash_equals() saat submit, agar situs lain tidak bisa mengirim ke form-mu atas nama pengunjung yang sedang login.
Uji validasi tanpa browser
Taruh aturannya di sebuah fungsi yang menerima array dan mengembalikan error-nya. Halaman memanggilnya dengan $_POST, dan kamu bisa memanggilnya dengan array apa pun, sehingga kasus-kasus tepi mudah dicoba. Tambahkan kasusmu sendiri ke daftarnya.
Kasus keempat adalah yang sering dilupakan. Sebuah request bisa mengirim name[]=x, yang membuat $_POST['name'] menjadi array, dan memberikan array ke trim() melempar TypeError serta menghentikan script. Memeriksa is_string() lebih dulu mengubah input yang berniat jahat menjadi error validasi biasa. Cast (string) di blok-blok sebelumnya juga mencegah TypeError, tetapi mengubah array menjadi kata Array dan mencetak warning, jadi is_string() adalah pemeriksaan yang lebih bersih.
Kesalahan umum: membaca $_POST sebelum form dikirim
Script form pertama yang paling umum membaca field-field di bagian atas file:
<?php
$name = $_POST['name'];
echo "Hello, $name";
Pada kunjungan pertama belum ada yang dikirim, jadi PHP mencetak:
Warning: Undefined array key "name" in /var/www/form.php on line 2
Solusinya adalah pola dari blok pertama: proses form hanya saat request-nya POST, dan baca setiap field dengan nilai default, $_POST['name'] ?? ''. Jika warning muncul setelah submit, bandingkan atribut name di HTML dengan key di PHP: name="Name" dan $_POST['name'] adalah key yang berbeda.
Pertanyaan yang sering diajukan
Bagaimana cara mengirim form PHP ke halaman yang sama?
Tulis <form method="post"> tanpa action (atau action=""). Browser mengirim kembali ke URL saat ini, jadi script yang sama menampilkan form sekaligus memprosesnya: periksa $_SERVER['REQUEST_METHOD'] === 'POST' dan baca field-nya dari $_POST.
Bagaimana cara menjaga nilai form setelah submit di PHP?
Cetak kembali nilai yang dikirim ke dalam field, dalam bentuk yang sudah di-escape: <input name="email" value="<?= htmlspecialchars($_POST['email'] ?? '') ?>">. Untuk checkbox cetak checked, dan untuk option select cetak selected, saat nilai yang dikirim cocok.
Bagaimana cara mendapatkan nilai beberapa checkbox di PHP?
Beri checkbox-checkbox itu nama yang sama dengan akhiran kurung siku, name="topics[]". PHP lalu memasukkan nilai yang dicentang ke sebuah array, $_POST['topics']. Checkbox yang tidak dicentang tidak mengirim apa pun, jadi pakai $_POST['topics'] ?? [] dan periksa setiap nilai terhadap daftar yang kamu tawarkan.
Kenapa me-refresh halaman mengirim ulang form PHP saya?
Request terakhir adalah POST, jadi browser mengulanginya saat refresh. Setelah submit berhasil, lakukan redirect dengan header('Location: /thanks.php'); exit; (pola Post/Redirect/Get). Refresh kemudian hanya mengulang GET yang tidak berbahaya.
Apakah $_POST aman dipakai di PHP?
Tidak, setiap nilai di $_POST datang dari pengunjung dan bisa berisi apa saja, termasuk HTML, SQL, atau array padahal kamu mengharapkan string. Validasi saat data masuk (filter_var, pemeriksaan panjang dan allowlist) dan escape saat data keluar (htmlspecialchars untuk HTML, prepared statement untuk SQL).