HTTP bersifat stateless: setiap request diperlakukan seolah datang dari orang asing yang belum pernah dikenali server. Cookie adalah mekanisme tertua untuk menyiasati keterbatasan tersebut. Server meminta browser menyimpan sepotong teks kecil, lalu browser secara otomatis mengirimkan teks tersebut kembali pada setiap request berikutnya ke domain yang sama. Dengan begitu aplikasi dapat mengingat tema pilihan, bahasa antarmuka, hingga tanda bahwa pengguna sudah login. Chapter ini membahas cara membuat cookie dengan setcookie(), membacanya melalui $_COOKIE, mengubah dan menghapusnya, serta batasan dan aturan aman dalam memilih data yang disimpan.

Cookie bekerja melalui dua header HTTP yang saling berpasangan. Ketika server ingin menyimpan cookie, server mengirimkan header respons Set-Cookie: nama=nilai kepada browser. Browser menyimpan pasangan nama-nilai tersebut, lalu pada setiap request berikutnya ke domain yang sama, browser menyertakan header permintaan Cookie: nama=nilai secara otomatis. PHP kemudian mengurai header Cookie tersebut dan menyediakan hasilnya dalam superglobal $_COOKIE sejak awal eksekusi skrip. Dengan demikian, cookie tersimpan sepenuhnya di sisi browser, bukan di server.

Fungsi setcookie() menerima nama cookie, nilai cookie, dan waktu kedaluwarsa berupa Unix timestamp. Jika timestamp diisi 0 atau dilewati, cookie berlaku sebagai session cookie yang dihapus begitu browser ditutup. Pada aplikasi nyata kita biasanya menulis time() + 3600 untuk cookie berumur satu jam; contoh di bawah memakai angka tetap agar hasilnya dapat diperiksa ulang secara deterministik.

php
<?php
$kadaluarsa = 1767225600; // 2026-01-01 00:00:00 UTC

$berhasil = setcookie('tema', 'gelap', $kadaluarsa);

echo 'Cookie tema tersimpan sampai: ' . date('Y-m-d H:i:s T', $kadaluarsa) . "\n";
var_dump($berhasil);

Output yang Dihasilkan:

text
Cookie tema tersimpan sampai: 2026-01-01 00:00:00 UTC
bool(true)

Mari kita telaah baris-baris kode di atas:

  1. Baris 2 ($kadaluarsa = ...): menyiapkan timestamp kedaluwarsa yang nilainya tetap, yaitu awal tahun 2026 UTC.
  2. Baris 4 (setcookie('tema', 'gelap', ...)): meminta PHP menyiapkan header Set-Cookie. Fungsi mengembalikan true ketika header berhasil disiapkan; perintah echo di baris 6 baru mengirim output setelah header siap.
  3. Baris 6 (date(...)): menampilkan tanggal dari timestamp yang sama, sehingga kita bisa memastikan makna angka kedaluwarsa tersebut.
  4. Baris 7 (var_dump($berhasil)): menegaskan bahwa pemanggilan setcookie() sukses mengembalikan true.

Perlu dicatat bahwa di lingkungan CLI tidak ada browser yang benar-benar menyimpan cookie; nilai balik true menunjukkan bahwa PHP berhasil menyiapkan header tersebut. Di lingkungan web dengan browser sungguhan, header inilah yang dibaca dan disimpan oleh browser.

setcookie() menulis header HTTP, dan header harus dikirim sebelum body respons. Jika ada output apa pun — echo, HTML di luar tag PHP, bahkan satu spasi — yang tercetak sebelum pemanggilan setcookie(), PHP memicu Warning: Cannot modify header information - headers already sent dan setcookie() mengembalikan false. Bandingkan dua urutan berikut:

php
<?php
// SALAH: output terkirim lebih dulu, header tidak bisa disusul
echo 'Selamat datang';

setcookie('tema', 'gelap');
php
<?php
// BENAR: semua setcookie() dipanggil sebelum output apa pun
setcookie('tema', 'gelap');
setcookie('bahasa', 'id');

echo 'Selamat datang';

Cookie yang dikirim browser tersedia dalam array superglobal $_COOKIE sejak request dimulai. Karena CLI tidak memiliki browser, kita mengisi $_COOKIE secara manual untuk mensimulasikan header Cookie: tema=gelap; bahasa=id yang dikirim browser sungguhan.

php
<?php
// Simulasi header permintaan: Cookie: tema=gelap; bahasa=id
$_COOKIE['tema'] = 'gelap';
$_COOKIE['bahasa'] = 'id';

echo 'Tema: ' . ($_COOKIE['tema'] ?? 'terang') . "\n";
echo 'Bahasa: ' . ($_COOKIE['bahasa'] ?? 'id') . "\n";
echo 'Font: ' . ($_COOKIE['font'] ?? 'sans-serif') . "\n";
echo 'Jumlah cookie diterima: ' . count($_COOKIE) . "\n";

Output yang Dihasilkan:

text
Tema: gelap
Bahasa: id
Font: sans-serif
Jumlah cookie diterima: 2

Perhatikan pola aksesnya:

  1. Baris 5-6: cookie yang memang dikirim langsung terbaca dari $_COOKIE.
  2. Baris 7: kunci font tidak pernah dikirim, sehingga operator ?? memberikan nilai default sans-serif tanpa memicu warning undefined array key.
  3. Baris 8: count() menghitung seluruh cookie yang diterima pada request ini.

Pengecekan keberadaan cookie dapat memakai isset($_COOKIE['font']) yang mengembalikan false untuk kunci yang tidak ada, atau array_key_exists() bila kita ingin membedakan kunci bernilai null.

Untuk mengubah cookie, kita cukup memanggil setcookie() dengan nama yang sama dan nilai baru; penulisan terakhir menimpa yang lama. Untuk menghapus cookie, kita mengirimkan cookie dengan nama yang sama, nilai kosong, dan waktu kedaluwarsa yang sudah lewat — begitu browser melihat tanggal kedaluwarsa di masa lalu, browser menghapus cookie tersebut dari penyimpanannya.

php
<?php
$ubah  = setcookie('tema', 'terang', 1767225600);
$hapus = setcookie('tema_lama', '', 1); // 1 detik setelah epoch = masa lalu

var_dump($ubah, $hapus);

Output yang Dihasilkan:

text
bool(true)
bool(true)

Angka 1 pada baris kedua adalah timestamp satu detik setelah 1 Januari 1970, jadi jelas sudah kedaluwarsa. Kedua pemanggilan sama-sama mengembalikan true karena keduanya hanya menyiapkan header; tindakan mengubah atau menghapus terjadi di sisi browser setelah header diterima.

Nilai Ter-encode dan setrawcookie #

Nilai cookie berbagi satu baris header dengan nama cookie, sehingga karakter seperti spasi, &, atau | harus di-encode agar header tetap valid. Fungsi setcookie() menerapkan URL-encoding pada nilai secara otomatis, dan PHP mendekode nilai tersebut kembali ketika mengisi $_COOKIE. Jika kita sudah memiliki nilai yang ter-encode dan ingin mengirimkannya apa adanya, gunakan setrawcookie() yang melewati proses encoding.

php
<?php
$rawOk   = setrawcookie('keranjang', 'Budi%7CSiti');
$contoh1 = rawurlencode('Budi Santoso');
$contoh2 = rawurlencode('keranjang[Budi|Siti]');

echo "'Budi Santoso' tersimpan sebagai: $contoh1\n";
echo "'keranjang[Budi|Siti]' tersimpan sebagai: $contoh2\n";
var_dump($rawOk);

Output yang Dihasilkan:

text
'Budi Santoso' tersimpan sebagai: Budi%20Santoso
'keranjang[Budi|Siti]' tersimpan sebagai: keranjang%5BBudi%7CSiti%5D
bool(true)

Fungsi rawurlencode() menunjukkan persis transformasi yang dilakukan setcookie() pada nilai cookie: spasi menjadi %20, tanda [ menjadi %5B, | menjadi %7C, dan seterusnya. Pada baris 2, setrawcookie() mengirim nilai Budi%7CSiti apa adanya tanpa encoding tambahan. Nilai yang dikirim melalui setrawcookie() memang harus sudah berbentuk aman seperti itu, karena tanda % atau karakter khusus mentah dapat merusak format header.

Cookie memiliki sejumlah batasan teknis yang memengaruhi desain aplikasi. Sebuah cookie hanya boleh berukuran sekitar 4 KB, dan browser membatasi jumlah cookie per domain dalam hitungan puluhan — angka pastinya berbeda antar browser. Cookie juga dikirim pada setiap request ke domain yang sama, sehingga cookie berukuran besar membebani bandwidth. Terakhir, pengguna dapat melihat, mengubah, dan menghapus cookie kapan saja dari menu browser, jadi isi cookie tidak boleh dipercaya kebenarannya.

KategoriContoh isiAlasan
Layak disimpanpreferensi tema, pilihan bahasa, ID non-sensitifkecil dan tidak merugikan bila dimanipulasi pengguna
Tidak layakpassword, nomor kartu kredit, token rahasiadapat dibaca dan diubah pengguna, ikut terkirim berulang kali

Data yang bersifat sensitif atau besar sebaiknya disimpan di server, dengan cookie hanya membawa pengenal untuk menemukan data tersebut. Mekanisme itulah yang disediakan PHP melalui session dan akan kita bahas beberapa chapter berikutnya.

Ringkasan #

Cookie adalah teks kecil yang disimpan browser dan dikirim ulang pada setiap request ke domain yang sama. Kita membuat cookie dengan setcookie() sebelum output apa pun, membacanya melalui $_COOKIE, menimpanya dengan nama yang sama, dan menghapusnya dengan kedaluwarsa di masa lalu. Karena cookie hidup di sisi browser dan dapat dimanipulasi pengguna, isinya harus dibatasi pada data yang tidak sensitif. setcookie() masih punya satu wajah lain yang belum kita bahas: array opsi yang mengatur secure, httponly, dan samesite — tombol-tombol keamanan penting yang menjadi fokus chapter berikutnya.

Referensi #