Store sudah dipilih, tabel cache siap, sekarang saatnya mengoperasikannya. Operasi cache sehari-hari sebenarnya berputar pada tiga kata kerja: simpan, baca, dan hapus. Laravel menyajikan semuanya lewat Cache facade, helper global cache(), dan satu pola yang menggabungkan ketiganya — remember() — yang akan kita pakai paling sering. Pada chapter ini kita jalankan setiap operasi di store database sehingga hasilnya bisa kita lihat persis apa adanya.
put, get, dan Nilai Default #
Menulis cache memakai Cache::put() dengan tiga argumen: kunci, nilai, dan masa hidup dalam detik. Membacanya memakai Cache::get(), dengan nilai cadangan bila kunci ternyata kosong:
use Illuminate\Support\Facades\Cache;
Cache::put('kota', 'Bandung', 300);
echo 'get: ' . Cache::get('kota') . "\n";
echo 'default: ' . var_export(Cache::get('negara', 'Indonesia'), true) . "\n";Output yang Dihasilkan:
get: Bandung
default: 'Indonesia'Argumen kedua get() hanya dipakai saat cache miss. Nilai apa pun bisa disimpan — string, angka, array, bahkan collection — karena store database men-serialize isinya ke kolom value.
Helper cache() menawarkan jalan pintas untuk kedua arah. Dipanggil dengan array, helper menulis; dipanggil dengan string, helper membaca; dan bentuk cache()->... mengembalikan repository lengkap sehingga semua method facade tersedia:
cache(['menu:aktif' => 'Beranda'], 300); // tulis
echo 'helper_put: ' . cache('menu:aktif') . "\n"; // baca
echo 'helper_remember: '
. cache()->remember('menu:judul', 300, fn () => 'Belajar Laravel') . "\n";Output yang Dihasilkan:
helper_put: menu:aktif=Beranda
helper_remember: Belajar Laravelremember(), Kuda Beban Cache #
Pola paling penting dalam ber-cache adalah cache-aside: coba baca dulu, jika kosong jalankan komputasi lalu simpan. Cache::remember() merangkai ketiga langkah itu dalam satu panggilan. Runner berikut membuktikan closure-nya benar-benar hanya berjalan sekali:
$panggilan = 0;
$hitung = function () use (&$panggilan) {
$panggilan++;
return 'jumlah-post: 3';
};
Cache::forget('stats:jumlah-post');
$miss = Cache::remember('stats:jumlah-post', 300, $hitung);
$hit = Cache::remember('stats:jumlah-post', 300, $hitung);
fwrite(STDERR, "remember: miss={$miss} hit={$hit} panggilan_closure={$panggilan}\n");Output yang Dihasilkan:
remember: miss=jumlah-post: 3 hit=jumlah-post: 3 panggilan_closure=1Panggilan pertama mengeksekusi closure (memicu cache miss), panggilan kedua dilayani dari cache tanpa menyentuh closure sama sekali. Dalam aplikasi nyata, panggilan remember() seperti ini biasanya tinggal di service atau controller — tepat di titik data dibutuhkan — sementara closure-nya berisi query Eloquent atau panggilan HTTP yang mahal. Berapa kali pun halaman itu dikunjungi dalam lima menit berikutnya, komputasi mahal di dalam closure tidak pernah diulang.
Untuk data yang pantas hidup selamanya, sepupunya rememberForever() menghilangkan argumen TTL, dan get() juga menerima closure sebagai nilai default sehingga kita bebas memilih gaya penulisan:
Cache::forget('negara');
$negara = Cache::get('negara', function () {
return 'dihitung ulang: Indonesia';
});
echo "closure_default: {$negara}\n";Output yang Dihasilkan:
closure_default: dihitung ulang: Indonesiaadd() dan Operasi Hitung #
Cache::add() adalah versi sopan dari put(): hanya menulis bila kunci belum ada, dan mengembalikan true/false sebagai laporan apakah penulisan terjadi. Perilaku ini berguna untuk menandai “pekerjaan sudah dimulai” tanpa menimpa hasil yang ada:
Cache::forget('kota');
$add1 = Cache::add('kota', 'Bandung', 300);
$add2 = Cache::add('kota', 'Surabaya', 300);
echo 'add_pertama=' . var_export($add1, true) . ' add_kedua=' . var_export($add2, true)
. ' nilai=' . Cache::get('kota') . "\n";Output yang Dihasilkan:
add_pertama=true add_kedua=false nilai=BandungPenulisan kedua ditolak karena kunci sudah terisi, sehingga nilai Bandung bertahan. Selanjutnya, increment() dan decrement() mengubah angka secara atomik — operasi baca-ubah-tulis dalam satu langkah, aman dari dua request yang menghitung bersamaan:
Cache::forget('counter:kunjungan');
Cache::add('counter:kunjungan', 0, 300); // pastikan kunci ada dulu
$a = Cache::increment('counter:kunjungan'); // 1
$b = Cache::increment('counter:kunjungan', 4); // 5
$c = Cache::decrement('counter:kunjungan', 2); // 3
echo "ret: inc={$a} inc4={$b} dec2={$c}\n";
echo 'get: ' . var_export(Cache::get('counter:kunjungan'), true) . "\n";Output yang Dihasilkan:
ret: inc=1 inc4=5 dec2=3
get: 3Operasi Massal dan pull() #
Untuk menulis banyak kunci sekaligus dengan TTL yang sama, putMany() menerima satu array, dan many() membaca beberapa kunci dalam satu panggilan:
Cache::forget('produk:1');
Cache::forget('produk:2');
Cache::putMany([
'produk:1' => 'Laptop Gaming',
'produk:2' => 'Mouse Ergonomis',
], 300);
$semua = Cache::many(['produk:1', 'produk:2', 'produk:3']);
echo 'many: ' . json_encode($semua, JSON_UNESCAPED_SLASHES) . "\n";Output yang Dihasilkan:
many: {"produk:1":"Laptop Gaming","produk:2":"Mouse Ergonomis","produk:3":null}Kunci yang tidak ada (produk:3) hadir sebagai null di hasil, bukan hilang dari array — posisi setiap nilai tetap sejajar dengan daftar kunci yang diminta, sehingga hasilnya mudah dipetakan kembali. Terakhir, pull() membaca sekaligus menghapus dalam satu langkah, pas untuk data sekali-pakai seperti token konfirmasi:
$nilai = Cache::pull('kota', 'kosong');
$lagi = Cache::pull('kota', 'kosong');
echo "pull_pertama={$nilai} pull_kedua={$lagi}\n";Output yang Dihasilkan:
pull_pertama=Bandung pull_kedua=kosongMenghapus Entri #
Cache::forget() menghapus satu kunci, sedangkan Cache::flush() mengosongkan seluruh store. Artisan menyediakan keduanya dari terminal:
$ php artisan cache:forget kota
INFO The [kota] key has been removed from the cache.Satu hal yang belum kita bahas serius adalah angka 300 yang terus muncul: berapa lama sebaiknya cache hidup, dan apa bedanya TTL berupa detik dengan objek Carbon? Itu fokus chapter Cache Expiration
, dan rujukan lengkap semua method di atas ada di dokumentasi Cache
.