Panggil session_start() di bagian atas halaman, lalu baca dan tulis $_SESSION['key'] seperti array biasa: PHP menyimpannya di server dan menemukannya lagi pada request pengunjung berikutnya. Untuk nilai kecil yang perlu disimpan browser, panggil setcookie('name', 'value', time() + 86400) dan baca kembali pada request berikutnya dari $_COOKIE['name'].
<?php
session_start(); // before any output
setcookie('theme', 'dark', time() + 60 * 60 * 24 * 30); // 30 days, also before output
$_SESSION['visits'] = ($_SESSION['visits'] ?? 0) + 1;
$theme = $_COOKIE['theme'] ?? 'light'; // set on an earlier visit
echo "You have opened this page {$_SESSION['visits']} times.";
Session dan cookie baru berguna di beberapa request HTTP dari browser, jadi contoh yang membutuhkannya ditulis sebagai kode biasa. Logika di sekitarnya hanyalah PHP biasa yang mengolah array, dan bagian itu bisa dijalankan di sini: di setiap blok yang bisa dijalankan, $session menggantikan $_SESSION, dan setiap panggilan adalah satu request.
Cara kerja session PHP
session_start()yang pertama membuat id acak, mengirimkannya ke browser dalam cookie bernamaPHPSESSID, dan memberimu$_SESSIONyang kosong.- Di akhir request, PHP menyimpan
$_SESSIONdi server (secara default dalam file, atau di Redis, atau di database). - Pada request berikutnya, browser mengirim cookie itu kembali, lalu
session_start()membaca id-nya dan memuat array yang tersimpan.
Browser tidak pernah melihat datanya, hanya id-nya. Karena itulah id user yang sedang login harus disimpan di $_SESSION dan tidak pernah di cookie buatanmu sendiri: pengunjung bisa mengubah cookie-nya menjadi nilai apa pun, tetapi tidak bisa mengubah $_SESSION.
Login dan logout user dengan session
Login berarti: periksa password, buat ulang session id, simpan id user. Logout adalah kebalikannya, dan terdiri dari tiga langkah.
<?php
// login.php
session_start();
$user = find_user_by_email($_POST['email'] ?? '');
if ($user && password_verify($_POST['password'] ?? '', $user['password_hash'])) {
session_regenerate_id(true); // new id after login: stops session fixation
$_SESSION['user_id'] = $user['id'];
header('Location: /dashboard.php');
exit;
}
$error = 'Wrong email or password.';
<?php
// any protected page
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: /login.php');
exit;
}
<?php
// logout.php
session_start();
$_SESSION = []; // 1. forget the data
$p = session_get_cookie_params(); // 2. delete the cookie
setcookie(session_name(), '', time() - 3600, $p['path'], $p['domain'], $p['secure'], $p['httponly']);
session_destroy(); // 3. delete the stored session
header('Location: /');
exit;
session_regenerate_id(true) lebih penting daripada kelihatannya. Kalau penyerang bisa membuat korban memakai session id yang diketahui penyerang (misalnya lewat sebuah link), dan id itu tetap sama setelah login, penyerang ikut login juga. Id baru saat login menutup celah itu. Pemeriksaan password sendiri dibahas di halaman password_hash.
Mengakhiri session setelah tidak ada aktivitas
Pembersihan bawaan PHP (session.gc_maxlifetime, default 1440 detik) berjalan secara acak dan bukan timeout yang bisa diandalkan. Simpan waktu request terakhir dan periksa sendiri. Blok ini memakai timestamp tetap supaya kamu bisa melihat setiap kasusnya; ubah $timeout atau waktunya.
Jeda dari 09:05 ke 09:16:40 adalah 700 detik, di bawah batas 15 menit, jadi user tetap login. Jeda berikutnya 1000 detik, jadi session-nya dikosongkan.
Flash message
Flash message diset pada satu request dan ditampilkan sekali pada request berikutnya, biasanya "Tersimpan." setelah redirect. Simpan di session, lalu baca dan hapus dalam satu langkah:
Menyimpan cookie dengan setcookie
setcookie() menerima nama, nilai, dan array opsi (PHP 7.3 ke atas). Pasang empat opsi ini di setiap cookie kecuali kamu punya alasan untuk tidak melakukannya:
<?php
setcookie('theme', 'dark', [
'expires' => time() + 60 * 60 * 24 * 30, // 30 days; 0 means "until the browser closes"
'path' => '/', // send it on every page, not just this folder
'secure' => true, // only over HTTPS
'httponly' => true, // JavaScript cannot read it
'samesite' => 'Lax', // not sent on most cross-site requests
]);
$theme = $_COOKIE['theme'] ?? 'light';
Ada dua hal yang sering bikin bingung:
$_COOKIEtidak berubah di request yang sama. Isinya adalah apa yang dikirim browser bersama request ini. Cookie yang kamu set sekarang baru muncul di$_COOKIEpada request berikutnya.- Cookie adalah header, jadi
setcookie()harus dijalankan sebelum output apa pun, persis sepertisession_start()danheader().
Untuk menghapus cookie, set ulang dengan nama dan path yang sama serta waktu kedaluwarsa di masa lalu: setcookie('theme', '', ['expires' => time() - 3600, 'path' => '/']).
Menyimpan array di cookie
Nilai cookie adalah string berukuran paling banyak sekitar 4 KB, jadi simpan data terstruktur sebagai JSON, dan perlakukan apa yang kembali sebagai input yang tidak bisa dipercaya: pengunjung bisa mengubahnya. Jangan pernah unserialize() sebuah cookie: fungsi itu bisa membuat objek dari class milikmu sendiri dan menjalankan magic method-nya, sedangkan json_decode() hanya pernah mengembalikan array, string, angka, boolean, null, atau stdClass.
Halaman json_encode membahas flag-nya. Untuk data yang lebih besar dari beberapa nilai pendek, simpan datanya di session (atau di database) dan simpan hanya sebuah key di cookie.
Token "remember me"
Cookie "remember me" tidak boleh berisi id user atau hash password. Simpan token acak yang panjang di cookie dan hanya hash-nya di database, lalu bandingkan dengan hash_equals():
Nilainya berubah setiap kali dijalankan, karena random_bytes() memang acak. Kalau database bocor, hash-hash itu tidak berguna tanpa cookie-nya, dan hash_equals() membandingkan dalam waktu konstan sehingga pemeriksaannya tidak membocorkan informasi waktu.
Session vs cookie: mana yang dipakai
Session ($_SESSION) | Cookie ($_COOKIE) | |
|---|---|---|
| Disimpan | Di server | Di browser |
| Pengunjung bisa membaca atau mengubahnya | Tidak (hanya id-nya) | Ya |
| Ukuran | Dibatasi oleh penyimpananmu | Sekitar 4 KB per cookie |
| Bertahan | Sampai browser ditutup atau session kedaluwarsa | Sampai waktu expires-nya |
| Dipakai untuk | User yang login, keranjang belanja, token CSRF, flash message | Tema, bahasa, pilihan persetujuan, token "remember me" |
Kesalahan umum: headers already sent
session_start(), setcookie(), dan header() semuanya mengirim header HTTP, dan header hanya bisa dikirim sebelum body. Output apa pun yang lebih dulu, bahkan satu baris kosong sebelum <?php di file yang di-include, menghasilkan:
Warning: session_start(): Session cannot be started after headers have already been sent in /var/www/page.php on line 3
Warning: Cannot modify header information - headers already sent by (output started at /var/www/page.php:2) in /var/www/page.php on line 4
Pesan kedua memberi tahu di mana output dimulai (page.php:2): buka baris itu dan hapus output-nya, atau pindahkan session_start() ke atasnya. Di file yang hanya berisi PHP, tidak menulis tag penutup ?> mencegah whitespace yang tersisa setelahnya menjadi output.
Pertanyaan yang sering diajukan
Apa bedanya session dan cookie di PHP?
Cookie disimpan di browser pengunjung dan dikirim bersama setiap request, jadi pengunjung bisa membaca dan mengubahnya. Session menyimpan datanya di server; browser hanya menyimpan session id acak di sebuah cookie (PHPSESSID). Simpan apa pun yang harus bisa dipercaya, seperti id user yang sedang login, di $_SESSION.
Bagaimana cara menghapus session saat logout di PHP?
Kosongkan datanya, hapus cookie session, lalu hapus session yang tersimpan: $_SESSION = [];, lalu setcookie(session_name(), '', time() - 3600, '/'), lalu session_destroy();. Lakukan redirect sesudahnya supaya halaman berikutnya mulai dari awal.
Bagaimana cara menghapus cookie di PHP?
Set ulang cookie itu dengan nama, path, dan domain yang sama, serta waktu kedaluwarsa di masa lalu: setcookie('theme', '', ['expires' => time() - 3600, 'path' => '/']);. Jalankan juga unset($_COOKIE['theme']) kalau bagian lain dari script yang sedang berjalan masih membacanya, karena $_COOKIE baru berubah pada request berikutnya.
Berapa lama session PHP bertahan?
Secara default, cookie session bertahan sampai browser ditutup (session.cookie_lifetime = 0) dan server boleh menghapus data session setelah 1440 detik (24 menit) tanpa aktivitas (session.gc_maxlifetime). Untuk timeout yang pasti, simpan waktu request terakhir di session dan periksa sendiri.
Kenapa session_start() bilang headers already sent?
Session id dikirim lewat header cookie, dan header harus dikirim sebelum output apa pun. Sebuah echo, HTML, atau bahkan baris kosong atau BOM sebelum <?php membuat output terkirim lebih dulu. Panggil session_start() di bagian paling atas script, sebelum apa pun dicetak.