Episode #60 kemarin kita belajar tidak mempercayai input user. Sekarang masalah sebaliknya: bagaimana PHP mengenali user yang sudah dipercaya? Setiap request HTTP itu independen dan pelupa, server tidak ingat kamu siapa di request sebelumnya. Padahal fitur login butuh ingatan: "user ini sudah login, jangan suruh login lagi tiap buka halaman". Episode #61 ini tentang session dan cookie, dua cara PHP punya ingatan, plus bonus upload file.
HTTP Itu Pelupa: Analogi Pelayan Amnesia
Bayangkan restoran dengan pelayan yang menderita amnesia total. Tiap kali kamu panggil, ia lupa kamu siapa, lupa kamu sudah pesan apa, dan memperlakukanmu seperti pelanggan baru. Itulah HTTP: protokol yang stateless. Setiap request adalah perkenalan pertama.
Tentu restoran sungguhan tidak begini. Solusinya: pelayan memberimu nomor meja (cookie), dan di dapur ada buku catatan yang mencatat "meja 7: sudah pesan, belum bayar" (session). Tiap kali kamu panggil, kamu sebut nomor mejamu, pelayan cek buku catatan, dan ia tahu riwayatmu. Persis begitu cara kerja session dan cookie di web.
Persepsi yang perlu diluruskan: banyak pemula mengira "kan sudah login, server pasti ingat". Tidak otomatis. Ingatan itu harus dibangun manual dengan session/cookie, dan kalau kamu tidak membangunnya, tiap halaman akan menganggap user belum login. Login yang "berhasil" tapi tidak pakai session itu cuma halaman ucapan selamat, bukan sistem login beneran.
Cookie: Titipan Kecil di Browser
Cookie adalah data kecil yang server titipkan ke browser, dan browser mengirimkannya balik di setiap request berikutnya. Isinya terlihat dan bisa diubah user, jadi jangan simpan data sensitif di sana. Cocok untuk preferensi ringan: tema gelap/terang, bahasa pilihan, "ingat saya".
<?php
// Menyimpan cookie 'tema' bernilai 'gelap', berlaku 30 hari
setcookie("tema", "gelap", time() + 30 * 24 * 3600);
// Membaca cookie
$tema = $_COOKIE["tema"] ?? "terang";
echo "Tema aktif: $tema";
?>
Dua aturan keras cookie. Pertama, setcookie harus dipanggil SEBELUM ada output apa pun (sebelum echo atau HTML). Kenapa? Karena cookie dikirim lewat HTTP header, dan header harus berangkat sebelum isi halaman. Kalau sudah terlanjur echo, PHP protes "headers already sent". Ini error klasik yang akan kamu temui minimal sekali, sekarang kamu tahu penyebabnya.
Kedua, cookie yang baru di-set belum bisa dibaca di request yang sama. $_COOKIE berisi cookie yang dikirim browser pada request ini, sedangkan cookie barumu baru dikirim ke browser sebagai respons. Ia baru terbaca saat user me-refresh atau buka halaman lain. Analoginya: kamu menitipkan catatan ke kurir, catatan itu belum sampai ke tujuan di detik yang sama kamu menitipkannya.
Session: Buku Catatan di Server
Session adalah ingatan yang disimpan di server, bukan di browser. Browser cuma menyimpan ID session (lewat cookie otomatis bernama PHPSESSID), sedangkan datanya aman di server dan tidak bisa diintip atau diubah user. Cocok untuk data sensitif: status login, id user, isi keranjang belanja.
<?php
session_start(); // WAJIB di baris paling atas, sebelum output apa pun
// Login berhasil: catat ke session
$_SESSION["user_id"] = 42;
$_SESSION["nama"] = "Adit";
// Di halaman lain: cek apakah sudah login
session_start();
if (isset($_SESSION["user_id"])) {
echo "Halo, " . htmlspecialchars($_SESSION["nama"]);
} else {
echo "Kamu belum login.";
}
// Logout: hapus semua data session
session_start();
session_destroy();
?>
Perhatikan session_start() wajib ada di SETIAP halaman yang memakai session, dan harus sebelum output apa pun (alasan header, sama seperti cookie). Lupa session_start adalah bug nomor satu pemula: $_SESSION tiba-tiba kosong padahal "tadi sudah diisi". Bukan datanya hilang, tapi sesinya belum dibuka.
Alur login sederhana yang benar: form POST username/password, validasi (episode #60), cek kredensial, kalau cocok isi $_SESSION, kalau tidak tampilkan error. Halaman yang butuh login cukup cek isset($_SESSION["user_id"]) di baris atas, kalau tidak ada, tendang ke halaman login. Pola tiga baris ini adalah fondasi semua sistem login PHP native.
Berhenti dan tebak dulu! Kode ini error "headers already sent". Kenapa?
<?php
echo "Selamat datang!";
session_start();
$_SESSION["nama"] = "Adit";
?>
Session vs Cookie: Kapan Pakai yang Mana
Pertanyaan yang bagus, karena pemula sering tertukar. Panduan praktisnya:
Pakai session untuk data yang sensitif atau tidak boleh diubah user: status login, id user, hak akses, keranjang belanja. Datanya di server, user cuma pegang ID acak yang tidak ada artinya.
Pakai cookie untuk preferensi ringan yang tidak masalah kalau user intip atau ubah: tema tampilan, bahasa, "sembunyikan banner ini". Datanya kecil dan tidak kritis.
Jangan pernah simpan password, walau sudah di-hash, di cookie. Jangan simpan "is_admin = true" di cookie karena user bisa mengubahnya jadi true dengan edit cookie di browser. Data otorisasi selalu di session.
Kuis cepat: Di mana data session disimpan?
Upload File: Menerima Berkas dari User
Fitur umum yang butuh penanganan khusus: upload foto profil, lampiran tugas, dan sejenisnya. Form-nya butuh dua syarat: method="post" dan enctype="multipart/form-data". Tanpa enctype yang benar, file tidak akan terkirim dan $_FILES kosong. Ini bug klasik nomor dua setelah lupa session_start.
<!-- form upload -->
<form method="post" enctype="multipart/form-data">
<input type="file" name="foto">
<button type="submit">Upload</button>
</form>
<?php
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$file = $_FILES["foto"];
// 1. Cek error upload
if ($file["error"] !== UPLOAD_ERR_OK) {
die("Upload gagal.");
}
// 2. Validasi ukuran (maks 2MB)
if ($file["size"] > 2 * 1024 * 1024) {
die("File terlalu besar, maks 2MB.");
}
// 3. Validasi tipe beneran (bukan cuma ekstensi nama file)
$boleh = ["image/jpeg", "image/png"];
if (!in_array($file["type"], $boleh)) {
die("Hanya boleh JPG atau PNG.");
}
// 4. Pindahkan dari folder sementara ke folder tujuan
$tujuan = "uploads/" . basename($file["name"]);
if (move_uploaded_file($file["tmp_name"], $tujuan)) {
echo "Upload berhasil!";
}
}
?>
Bedah alur berpikir keamanannya, karena upload file adalah pintu masuk favorit peretas. File yang diupload mendarat dulu di folder sementara (tmp_name), dan HANYA boleh dipindah dengan move_uploaded_file, fungsi yang memastikan file itu memang hasil upload HTTP, bukan file sistem yang dimanipulasi.
Validasi tipe jangan percaya ekstensi nama file: virus.exe bisa diganti nama jadi foto.jpg. Cek $file["type"] (tipe MIME yang dilaporkan) sebagai pertahanan pertama, dan untuk aplikasi serius cek isi file beneran. Validasi ukuran mencegah user mengupload film 4GB ke server kentangmu. Tiga lapis pertahanan: error, ukuran, tipe, baru pindahkan.
Berhenti dan tebak dulu! Form upload sudah benar tapi $_FILES selalu kosong. Apa yang paling mungkin lupa?
<form method="post">
<input type="file" name="foto">
<button type="submit">Upload</button>
</form>
Latihan dan Langkah Berikutnya
Latihan 1. Bikin sistem login mini dua file: login.php (form username/password, kredensial hardcode misal admin/12345, pakai validasi episode #60) dan dashboard.php yang hanya bisa dibuka kalau sudah login (cek session, kalau belum tendang balik ke login.php). Tambahkan logout.php yang menghancurkan session.
Latihan 2. UBAH latihan 1: setelah login berhasil, simpan juga waktu login ke session dan tampilkan di dashboard ("Login pada jam ..."). Lalu TAMBAHKAN fitur "ingat saya" pakai cookie: kalau dicentang, cookie menyimpan username supaya form login terisi otomatis saat dibuka lagi.
Latihan 3. Bikin upload.php untuk upload foto profil dengan semua validasi di artikel ini (error, ukuran maks 2MB, hanya JPG/PNG), plus satu validasi tambahan buatanmu: tolak file yang namanya mengandung spasi (petunjuk: pakai str_contains). Tampilkan gambar yang berhasil diupload di halaman yang sama.
Di episode #62 kita menutup series PHP Native dengan proyek beneran: koneksi ke MySQL dan operasi CRUD, dirangkai jadi aplikasi buku tamu. Di sanalah semua episode #56 sampai #61 menyatu: form, validasi, dan database. Sampai jumpa di proyek penutup.
Diskusi & Komentar 0
Punya tanggapan, pertanyaan, atau tips seputar tutorial ini? Tulis komentar kamu di bawah!
Jadilah yang pertama membuka obrolan dan berbagi pandangan seputar tutorial resep kode ini.
Tulis Komentar
Komentar menggunakan akun Google. Harap berkomentar dengan santun dan berbobot.