Cookie menyelesaikan masalah ingatan HTTP, tetapi membawa kelemahan serius: seluruh data tersimpan di browser, bisa dilihat, diubah, dan dipalsukan oleh pengguna. Session membalik posisinya — data disimpan di server, sementara cookie hanya membawa satu hal: ID session yang acak. Browser mengirim ID tersebut pada setiap request, PHP mencarinya di penyimpanan server, lalu memuat data yang bersangkutan ke superglobal $_SESSION. Chapter ini membahas cara memulai session, menulis dan membaca datanya, pola login dan logout, sampai bagaimana PHP membersihkan data lama secara otomatis.
Session Menyimpan Data di Server, Cookie Hanya Membawa Kunci #
Mekanisme session berjalan dalam empat langkah. Pertama, session_start() membaca cookie PHPSESSID dari request; jika tidak ada, PHP membuat ID acak baru dan menyiapkan header Set-Cookie untuk browser. Kedua, PHP mencari data session dengan ID tersebut di penyimpanan — secara bawaan berupa file di server. Ketiga, PHP memuat data tersebut ke array $_SESSION yang bisa kita baca dan tulis seperti array biasa. Keempat, di akhir request, PHP menulis kembali isi $_SESSION ke penyimpanan. Karena data asli ada di server, ukurannya tidak dibatasi 4 KB seperti cookie, dan pengguna tidak bisa memanipulasi isinya secara langsung.
Memulai Session dengan session_start() #
session_start() harus dipanggil sebelum output apa pun, karena fungsi tersebut turut mengatur header Set-Cookie. Pada contoh berikut kita menangkap nilai session_status() sebelum dan sesudah memulai session untuk melihat perubahan statusnya — nilai baru dicetak di akhir agar tidak ada output sebelum session_start().
<?php
$dir = sys_get_temp_dir() . '/php-kursus-sesi';
if (!is_dir($dir)) {
mkdir($dir);
}
session_save_path($dir); // arahkan penyimpanan ke lokasi khusus
session_id('fixed-session-id-123'); // ID tetap agar contoh dapat diulang
$statusSebelum = session_status(); // tangkap dulu, jangan dicetak
session_start();
$statusSesudah = session_status();
echo 'Sebelum start: ' . $statusSebelum . ' (PHP_SESSION_NONE)' . "\n";
echo 'Sesudah start: ' . $statusSesudah . ' (PHP_SESSION_ACTIVE)' . "\n";Output yang Dihasilkan:
Sebelum start: 1 (PHP_SESSION_NONE)
Sesudah start: 2 (PHP_SESSION_ACTIVE)Mari kita telaah baris-baris kode di atas:
- Baris 2-5: menyiapkan direktori penyimpanan khusus untuk demo, karena build CLI ini tidak mengatur
session.save_path. - Baris 8 (
session_save_path()): menunjuk lokasi file session sebelum session dimulai. - Baris 9 (
session_id(...)): memakai ID tetap sehingga hasil contoh konsisten antar eksekusi. - Baris 10-12: status
1(PHP_SESSION_NONE) berarti session belum aktif; setelahsession_start(), status menjadi2(PHP_SESSION_ACTIVE).
Menulis dan Membaca Data pada $_SESSION #
Setelah session aktif, $_SESSION adalah array superglobal biasa: kita menulis dengan assignment dan membaca seperti membaca array mana pun. Isinya boleh berupa integer, string, array, hingga object.
<?php
$dir = sys_get_temp_dir() . '/php-kursus-sesi';
if (!is_dir($dir)) {
mkdir($dir);
}
session_save_path($dir);
session_id('demo-data');
session_start();
$_SESSION['user_id'] = 42;
$_SESSION['nama'] = 'Budi';
$_SESSION['keranjang'] = ['buku' => 2, 'pensil' => 5];
echo 'user_id: ' . $_SESSION['user_id'] . "\n";
echo 'nama: ' . $_SESSION['nama'] . "\n";
echo 'keranjang: ' . json_encode($_SESSION['keranjang']) . "\n";
echo 'Jenis barang di keranjang: ' . count($_SESSION['keranjang']) . "\n";Output yang Dihasilkan:
user_id: 42
nama: Budi
keranjang: {"buku":2,"pensil":5}
Jenis barang di keranjang: 2Baris 11-13 menulis tiga data dengan tipe berbeda: integer ID pengguna, string nama, dan array asosiatif keranjang belanja. Baris 15-18 membacanya kembali dan menunjukkan bahwa array di dalam session tetap bisa diolah dengan fungsi array standar seperti count(). Seluruh nilai ini akan tersimpan di server begitu request selesai.
Membuktikan Data Bertahan Antar-Request #
Ciri khas session adalah daya ingatnya lintas request. Pada aplikasi web nyata, tiga request berarti tiga proses PHP terpisah; pada demo CLI ini kita menirunya dengan siklus session_start() → akses data → session_write_close() di dalam satu proses. Penutupan session menulis data ke penyimpanan, persis seperti yang dilakukan PHP otomatis di akhir request sungguhan.
<?php
$dir = sys_get_temp_dir() . '/php-kursus-sesi';
if (!is_dir($dir)) {
mkdir($dir);
}
session_save_path($dir);
session_id('demo-kunjungan');
@unlink($dir . '/sess_demo-kunjungan'); // reset sisa demo sebelumnya
$log = [];
for ($request = 1; $request <= 3; $request++) {
session_start();
$_SESSION['kunjungan'] = ($_SESSION['kunjungan'] ?? 0) + 1;
$log[] = "Request $request melihat kunjungan ke-" . $_SESSION['kunjungan'];
session_write_close();
}
echo implode("\n", $log), "\n";Output yang Dihasilkan:
Request 1 melihat kunjungan ke-1
Request 2 melihat kunjungan ke-2
Request 3 melihat kunjungan ke-3Perhatikan hasilnya: angka kunjungan terus bertambah dari request ke request, meskipun setiap siklus dimulai dengan session_start() yang membaca ulang penyimpanan. Baris @unlink di awal menghapus file demo dari eksekusi sebelumnya sehingga penghitungan selalu mulai dari satu. Seluruh pesan dikumpulkan ke $log dan baru dicetak setelah loop selesai, karena session_start() tidak boleh dipanggil setelah output dikirim.
Di Mana Data Session Disimpan #
Secara bawaan PHP menyimpan session sebagai file bernama sess_<id> di direktori yang ditentukan session.save_path. Isi file tersebut adalah data $_SESSION dalam format serialisasi khusus session. Kita bisa melihat format tersebut melalui session_encode():
<?php
$dir = sys_get_temp_dir() . '/php-kursus-sesi';
if (!is_dir($dir)) {
mkdir($dir);
}
session_save_path($dir);
session_id('demo-isi-file');
@unlink($dir . '/sess_demo-isi-file');
session_start();
$_SESSION['user_id'] = 42;
$_SESSION['nama'] = 'Budi';
$encode = session_encode();
session_write_close();
echo 'Bentuk ter-encode: ' . $encode . "\n";
echo 'Isi file sess_demo-isi-file: ' . var_export(file_get_contents($dir . '/sess_demo-isi-file'), true) . "\n";Output yang Dihasilkan:
Bentuk ter-encode: user_id|i:42;nama|s:4:"Budi";
Isi file sess_demo-isi-file: 'user_id|i:42;nama|s:4:"Budi";'Format user_id|i:42;nama|s:4:"Budi"; memetakan setiap kunci ke nilai yang diserialisasi — i:42 berarti integer 42, s:4:"Budi" berarti string sepanjang empat karakter. Handler penyimpanan bawaan bernama files menuliskan format tersebut apa adanya ke file. Kita tidak perlu mengolah format ini secara manual; menulis dan membaca cukup lewat $_SESSION.
Pola Login dengan Session #
Pola dasar login menyimpan identitas minimal — biasanya user_id — di session, bukan data sensitif seperti password. Request berikutnya cukup memeriksa keberadaan kunci tersebut untuk mengetahui bahwa pengguna sudah terautentikasi.
<?php
$dir = sys_get_temp_dir() . '/php-kursus-sesi';
if (!is_dir($dir)) {
mkdir($dir);
}
session_save_path($dir);
session_id('demo-login');
@unlink($dir . '/sess_demo-login');
$hasil = [];
// "Request 1": proses login
session_start();
$passwordCocok = true; // aplikasi nyata: password_verify() terhadap hash
if ($passwordCocok) {
session_regenerate_id(true); // ganti ID setelah login - lihat chapter Session Regeneration
$_SESSION['user_id'] = 42;
$_SESSION['nama'] = 'Budi';
$hasil[] = 'Login berhasil, identitas disimpan di session';
}
session_write_close();
// "Request 2": halaman berikutnya, ID sama dipakai lagi
session_start();
$hasil[] = 'Halo, ' . ($_SESSION['nama'] ?? 'tamu');
$hasil[] = 'Sudah login: ' . var_export(isset($_SESSION['user_id']), true);
session_write_close();
echo implode("\n", $hasil), "\n";Output yang Dihasilkan:
Login berhasil, identitas disimpan di session
Halo, Budi
Sudah login: trueRequest kedua tidak lagi memeriksa password — cukup membaca $_SESSION yang dimuat dari penyimpanan berdasarkan ID yang sama. Pemanggilan session_regenerate_id(true) setelah login adalah pertahanan wajib terhadap session fixation yang akan kita bedah tuntas pada chapter Session Regeneration
.
Logout dengan session_unset() dan session_destroy() #
Logout yang benar membersihkan dua hal: data di memori untuk request berjalan dan data tersimpan di server. session_unset() mengosongkan array $_SESSION, sedangkan session_destroy() menghapus data session dari penyimpanan server.
<?php
$dir = sys_get_temp_dir() . '/php-kursus-sesi';
if (!is_dir($dir)) {
mkdir($dir);
}
session_save_path($dir);
session_id('demo-logout');
@unlink($dir . '/sess_demo-logout');
// Login singkat untuk keperluan demo
session_start();
$_SESSION['user_id'] = 42;
$hasil = ['Sebelum logout: ' . count($_SESSION) . ' elemen data'];
// Proses logout
session_unset();
$hasil[] = 'Setelah session_unset(): ' . count($_SESSION) . ' elemen data';
$hasil[] = 'user_id masih terbaca: ' . var_export(isset($_SESSION['user_id']), true);
session_destroy();
$hasil[] = 'File session masih ada: ' . var_export(file_exists($dir . '/sess_demo-logout'), true);
echo implode("\n", $hasil), "\n";Output yang Dihasilkan:
Sebelum logout: 1 elemen data
Setelah session_unset(): 0 elemen data
user_id masih terbaca: false
File session masih ada: falseHasil eksekusi menunjukkan pembagian tugas kedua fungsi: setelah session_unset() array $_SESSION kosong, dan setelah session_destroy() file penyimpanannya pun lenyap dari server. Ketiga fungsi pengelolaan session ini punya peran yang berbeda:
| Fungsi | Yang dibersihkan | Kapan dipakai |
|---|---|---|
session_unset() | array $_SESSION di memori request ini | mengosongkan data tanpa menghapus session |
session_destroy() | data tersimpan di server | logout |
session_regenerate_id(true) | tidak membersihkan, mengganti ID | setelah login atau kenaikan hak akses |
Perlu dicatat bahwa session_destroy() tidak menghapus cookie PHPSESSID di browser, sehingga logout yang tuntas juga menimpa cookie tersebut dengan kedaluwarsa di masa lalu — pola lengkapnya akan kita lihat pada chapter Session Regeneration.
Garbage Collection Session #
File session yang ditinggalkan pengguna tidak boleh menumpuk selamanya. PHP menjalankan garbage collection (GC) secara probabilistik: dengan pengaturan bawaan session.gc_probability = 1 dan session.gc_divisor = 100, setiap kali session_start() dipanggil ada peluang 1% proses tersebut sekaligus memicu pembersihan. GC lalu menghapus file session yang tidak aktif lebih lama dari session.gc_maxlifetime, yang bawaannya 1440 detik atau 24 menit. Konsekuensinya, data session tidak dijamin lenyap tepat pada detik ke-1441 — penghapusan terjadi kapan pun peluang GC terpenuhi. Cara membaca dan mengubah seluruh angka-angka ini menjadi bahasan chapter Session Configuration
berikutnya.
Ringkasan #
Session menyimpan data di server dan hanya mempercayakan ID acak kepada browser: session_start() memuat data ke $_SESSION, assignment menulis data, dan session_write_close() menyimpannya kembali. Pola login cukup menyimpan user_id di session dan memeriksa keberadaannya di request berikutnya, sementara logout mengombinasikan session_unset() dan session_destroy(). Data lama dibersihkan GC secara probabilistik berdasarkan gc_maxlifetime. Seluruh perilaku ini dikendalikan belasan direktif php.ini — simpanan, umur, hingga mode keamanan — yang akan kita baca dan ubah pada chapter berikutnya.