Menyimpan state antar request dengan session, memakai flashdata untuk pesan sekali tampil, mengelola cookie, serta membangun alur login dan logout sederhana sebagai fondasi autentikasi penuh di episode 12.

HTTP itu stateless: setiap request berdiri sendiri, dan server tidak mengingat siapa yang mengirim request sebelumnya. Tanpa mekanisme tambahan, aplikasi tidak bisa tahu "user ini sudah login" atau "user ini mengisi form yang gagal validasi".
Di episode 9 ini kita memecahkan masalah itu dengan session, flash data, dan cookies. Konsep ini adalah fondasi untuk autentikasi (episode 12) dan sekaligus menjelaskan kenapa with('errors', ...) di episode 8 bisa "selamat" lewat redirect — karena ia disimpan di session.
Session adalah data yang disimpan di server, diidentifikasi lewat cookie di browser. Alurnya:
CodeIgniter mengelola semuanya lewat helper session(). Konfigurasi ada di app/Config/Session.php:
| Property | Arti |
|---|---|
$driver | Tempat penyimpanan: FileHandler, RedisHandler, DatabaseHandler |
$savePath | Path/target penyimpanan (default writable/session) |
$expiration | Lama session hidup (detik), default 7200 |
$cookieName | Nama cookie session |
$matchIP | Validasi alamat IP (false default) |
$session = session();
// SET - simpan nilai
$session->set('user_id', 1);
$session->set(['role' => 'admin', 'last_login' => time()]);
// GET - ambil nilai
$user_id = $session->get('user_id');
$role = $session->get('role');
// HAS - cek keberadaan
if ($session->has('user_id')) {
// user sudah login
}
// REMOVE & DESTROY
$session->remove('user_id');
$session->destroy(); // bersihkan seluruh session + cookieSelalu gunakan session() helper — ia mengembalikan instance singleton yang sama untuk seluruh request, jadi set di satu tempat terbaca di tempat lain.
Flashdata adalah data session yang otomatis terhapus setelah dibaca sekali — sempurna untuk pesan sukses/error setelah redirect.
// Simpan (misal di controller setelah aksi sukses)
session()->setFlashdata('success', 'Post berhasil disimpan');
// Baca (di view tujuan)
<?php if (session('success')): ?>
<div class="alert alert-success"><?= esc(session('success')) ?></div>
<?php endif; ?>session('success') di view adalah shortcut untuk session()->getFlashdata('success'). Flashdata hanya tersedia untuk satu request berikutnya — setelah dibaca, ia hilang. Itulah alasan pesan tidak muncul berulang saat halaman di-refresh.
Tip
Flashdata sangat cocok untuk pola PRG (Post-Redirect-Get): controller mengolah POST, redirect, lalu view menampilkan pesan sekali. Pola ini juga mencegah form terkirim ulang saat user menekan refresh.
Cookie disimpan di browser, bukan di server. CodeIgniter menyediakan helper cookie:
helper('cookie');
// SET - simpan cookie
set_cookie('theme', 'dark', 3600); // nama, nilai, durasi detik
set_cookie('locale', 'id', [
'expire' => 86400 * 30,
'httponly' => false, // dibaca JavaScript
]);
// GET - baca cookie
$theme = get_cookie('theme');
// DELETE - hapus cookie
delete_cookie('theme');Bedanya dengan session: cookie terlihat oleh client (bisa dibaca JavaScript) dan mengalir tiap request. Karena itu jangan pernah menyimpan data sensitif (user id, role) di cookie tanpa enkripsi. Aturan praktis: cookie untuk preferensi, session untuk state autentikasi.
Warning
Jangan menyimpan role atau user_id di cookie dan mempercayainya di server — cookie bisa dipalsukan client. Jika butuh, simpan nilai terenkripsi atau (lebih baik) simpan di session server. Kita koreksi hal ini di episode 12 dan 20.
Gabungkan semuanya dalam alur login minimal. Model user (dari skema episode 7) dan controller auth:
<?php
namespace App\Controllers;
use App\Models\UserModel;
class Auth extends BaseController
{
public function login(): string | \CodeIgniter\HTTP\RedirectResponse
{
if (session()->get('logged_in')) {
return redirect()->to('/dashboard');
}
return view('auth/login');
}
public function attempt(): \CodeIgniter\HTTP\RedirectResponse
{
$rules = [
'email' => 'required|valid_email',
'password' => 'required',
];
if (! $this->validate($rules)) {
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
}
$email = $this->request->getPost('email');
$password = $this->request->getPost('password');
$user = (new UserModel())->where('email', $email)->first();
if ($user === null || ! password_verify($password, $user['password'])) {
return redirect()->back()->with('error', 'Email atau password salah');
}
session()->set([
'logged_in' => true,
'user_id' => $user['id'],
'name' => $user['name'],
]);
return redirect()->to('/dashboard')->with('success', 'Selamat datang!');
}
public function logout(): \CodeIgniter\HTTP\RedirectResponse
{
session()->destroy();
return redirect()->to('/login');
}
}Alurnya: attempt() memvalidasi input, mencari user di database, memverifikasi password dengan password_verify(), lalu menyimpan identitas di session. logout() menghancurkan session. Jangan lupa route-nya:
$routes->get('login', 'Auth::login');
$routes->post('login', 'Auth::attempt');
$routes->get('logout', 'Auth::logout');Warning
Alur ini masih minim perlindungan — belum ada proteksi brute force, belum ada session regenerate, dan dashboard bisa diakses tanpa login. Semua itu akan kita perkuat di episode 12 dengan autentikasi penuh dan filter, serta episode 19 dengan rate limiting.
session() untuk set/get/has/remove/destroy.app/Config/Session.php: driver, save path, expiration.setFlashdata) untuk pesan sekali tampil — pola PRG.Inti yang harus dibawa pulang:
password_verify(), jangan pernah bandingkan password plaintext.Di episode 10 selanjutnya kita akan membahas helpers & libraries — helper bawaan seperti url, form, html, dan text; membuat custom helper; serta custom library dengan registrasi service dan autoload. Ini senjata untuk menulis kode yang DRY (Don't Repeat Yourself)!