Validasi data di PHP tanpa framework bergantung pada beberapa fungsi bawaan: filter_var(), ctype_*, ekspresi reguler, atau pengecekan manual dengan kondisi biasa. Pilihan terbaik tergantung jenis data yang diperiksa dan seberapa ketat aturannya. Panduan ini membandingkan tujuh cara yang paling sering dipakai pemula, lengkap dengan contoh dan situasi yang cocok untuk masing-masing.
Kenapa validasi tidak cukup di sisi browser
Validasi JavaScript di form cepat memberi umpan balik ke pengguna. Tapi semua yang dikirim browser bisa dimodifikasi, dimatikan, atau dikirim ulang lewat alat seperti curl. Server tetap harus memeriksa ulang setiap nilai yang masuk. Tanpa itu, data kosong, tipe salah, atau karakter berbahaya bisa lolos ke database.
Validasi di PHP punya dua lapis tugas. Pertama memastikan data sesuai format yang diharapkan. Kedua mencegah data yang tidak sah diproses lebih lanjut. Keduanya berbeda dari sanitasi, yang mengubah data sebelum disimpan atau ditampilkan.
1. filter_var() untuk email, URL, dan IP
filter_var() adalah pilihan pertama untuk data yang formatnya sudah standar. Fungsi ini memakai filter bawaan PHP sehingga kamu tidak perlu menulis pola sendiri.
$email = $_POST['email'];
if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
echo 'Email tidak valid';
}
Perhatikan perbandingan dengan === false. Fungsi ini mengembalikan nilai asli kalau lolos, dan false kalau gagal. Untuk angka gunakan FILTER_VALIDATE_INT atau FILTER_VALIDATE_FLOAT, dan untuk URL pakai FILTER_VALIDATE_URL.
Keterbatasannya: filter email PHP mengikuti aturan teknis, bukan aturan penyedia email. Alamat seperti a@b bisa dianggap valid meski tidak lazim. Untuk kebutuhan ketat, filter ini perlu ditambah pemeriksaan domain.
2. ctype_* untuk karakter dan angka
Kelompok fungsi ctype_* memeriksa apakah seluruh string hanya berisi karakter tertentu. ctype_digit() memastikan isinya angka, ctype_alpha() memastikan huruf, dan ctype_alnum() memastikan huruf serta angka.
ctype_digit()cocok untuk NIK, nomor telepon, atau kode pos.ctype_alpha()cocok untuk nama tanpa spasi atau gelar.ctype_alnum()cocok untuk username tanpa simbol.
Fungsi ini cepat dan mudah dibaca. Kekurangannya, ctype_digit() mengembalikan false untuk string kosong, dan hasilnya bisa berbeda untuk string dengan karakter non-ASCII. Pakai fungsi ini untuk input yang memang hanya berisi huruf atau angka Latin.
3. Ekspresi reguler dengan preg_match()
Kalau aturan format terlalu spesifik untuk filter bawaan, regex jadi jalan keluar. Contohnya kode pos Indonesia yang selalu lima digit, atau nomor HP dengan awalan tertentu.
$kodePos = $_POST['kode_pos'];
if (!preg_match('/^[0-9]{5}$/', $kodePos)) {
echo 'Kode pos harus 5 digit';
}
Regex sangat kuat, tapi juga mudah salah. Pola yang salah bisa meloloskan data yang seharusnya ditolak, atau menolak data yang benar. Selalu uji pola dengan beberapa contoh positif dan negatif sebelum dipakai. Hindari menulis pola panjang dalam satu baris tanpa komentar; pada pola yang rumit, jelaskan maksud tiap bagian lewat komentar kode PHP agar mudah dirawat.
4. Pengecekan manual dengan kondisi biasa
Untuk aturan yang tidak soal format, seperti rentang umur atau panjang minimal, kondisi if biasa lebih jelas daripada regex.
if (strlen($nama) < 3 || strlen($nama) > 50) {
echo 'Nama harus 3 sampai 50 karakter';
}
if ($umur < 17 || $umur > 100) {
echo 'Umur di luar rentang yang diterima';
}
Kombinasikan dengan trim() sebelum memeriksa, karena spasi di awal dan akhir sering membuat panjang string salah hitung. Untuk input yang boleh kosong, cek dulu dengan isset, empty, dan null coalescing agar tidak memicu peringatan.
5. Validasi array dengan filter_var_array()
Form dengan banyak kolom membuat kode validasi cepat menumpuk. filter_var_array() memeriksa seluruh array sekaligus dengan definisi filter per kunci.
$data = filter_var_array($_POST, [
'nama' => FILTER_SANITIZE_SPECIAL_CHARS,
'email' => FILTER_VALIDATE_EMAIL,
'umur' => ['filter' => FILTER_VALIDATE_INT,
'options' => ['min_range' => 17]],
]);
Hasilnya array berisi nilai yang lolos filter, atau false untuk yang gagal. Kamu masih perlu memeriksa hasil per kunci untuk menyusun pesan error yang jelas. Untuk pola pengambilan data dari form, lihat juga cara menangani form input di PHP untuk pemula.
6. Validasi berbasis aturan dengan class kecil
Kalau satu form punya belasan aturan, menulis if berulang membuat fungsi validasi panjang dan susah dites. Kamu bisa membuat class sederhana yang menyimpan daftar aturan per kolom.
class Validator {
private array $errors = [];
public function rule(string $field, string $value, callable $check, string $message): void {
if (!$check($value)) {
$this->errors[$field] = $message;
}
}
public function errors(): array {
return $this->errors;
}
}
Pemakaiannya: panggil rule() untuk tiap aturan, lalu periksa errors() setelah semua aturan dijalankan. Pola ini berguna saat form punya banyak kolom dan kamu ingin mengumpulkan semua error sekaligus, bukan berhenti di kesalahan pertama.
Kalau form divalidasi di server dan di browser sekaligus, bagi tugasnya dengan jelas. Aturan yang menyangkut keamanan dan integritas data selalu diulang di server, sementara browser menangani umpan balik cepat. Pembagian ini mirip dengan pola penanganan input dinamis pada pencarian langsung dengan JavaScript dan PHP, di mana query tetap disaring di sisi server.
7. Sanitasi setelah validasi
Validasi memastikan data sesuai aturan; sanitasi membersihkan data sebelum dipakai. Keduanya bukan pengganti satu sama lain. Gunakan FILTER_SANITIZE_* atau htmlspecialchars() saat data akan ditampilkan ke halaman, dan prepared statement saat data masuk ke database.
htmlspecialchars()untuk teks yang dicetak ke HTML.filter_var($url, FILTER_SANITIZE_URL)untuk tautan yang disimpan.- Prepared statement untuk semua nilai yang dikirim ke query.
Untuk beberapa jenis input, sanitasi juga dilakukan lewat aturan penulisan nilai tetap seperti konstanta. Pola ini dibahas di cara mendefinisikan konstanta di PHP, dan berguna untuk daftar pilihan yang sah.
Perbandingan singkat
| Teknik | Cocok untuk | Kelemahan |
|---|---|---|
| filter_var() | Email, URL, IP, angka | Terlalu longgar untuk aturan khusus |
| ctype_* | String huruf/angka murni | Perilaku beda pada karakter non-ASCII |
| preg_match() | Format spesifik | Pola mudah salah |
| Kondisi manual | Rentang dan panjang | Kode menumpuk di form besar |
| filter_var_array() | Banyak kolom sekaligus | Pesan error perlu disusun sendiri |
| Class validator | Aturan banyak dan berulang | Perlu struktur tambahan |
Untuk urusan aturan yang rumit, memilih pola validasi mirip dengan memilih pola lain di PHP: ambil yang paling sederhana namun tetap terbaca. Kalau butuh membandingkan pola kode lain, perbandingan loop jQuery each(), for, dan map() memberi contoh cara menimbang beberapa opsi dengan kriteria yang jelas.
Ringkasan
Mulai dari filter_var() untuk data berformat standar, tambahkan ctype_* atau regex untuk aturan khusus, dan pakai kondisi manual untuk rentang nilai. Saat form makin besar, pindahkan aturan ke fungsi atau class agar mudah diuji. Jangan lupa sanitasi dan prepared statement sebagai lapisan terakhir sebelum data disimpan atau ditampilkan.
Pertanyaan yang Sering Diajukan
Apakah validasi JavaScript bisa menggantikan validasi PHP?
Tidak. JavaScript berjalan di browser pengguna dan bisa dilewati, sedangkan validasi PHP berjalan di server tempat kamu punya kendali penuh. Pakai keduanya: JavaScript untuk umpan balik cepat, PHP untuk memastikan data benar-benar aman.
Kapan sebaiknya pakai regex daripada filter_var()?
Gunakan regex jika formatnya tidak tersedia di filter bawaan, misalnya kode pos lima digit atau nomor dokumen dengan awalan tertentu. Untuk email, URL, dan IP, filter bawaan lebih mudah dibaca dan cukup untuk sebagian besar kebutuhan.
Apakah sanitasi sudah cukup tanpa validasi?
Belum. Sanitasi mengubah data agar aman ditampilkan, tapi tidak memastikan isinya masuk akal. Data seperti email berisi spasi bisa lolos sanitasi namun tetap salah format. Jalankan validasi dulu, baru sanitasi sesuai konteks pemakaian.