Chapter sebelumnya membuktikan cache menyimpan salinan hasil komputasi di tabel cache aplikasi kita. Sebenarnya tabel database hanyalah salah satu tempat untuk menyimpan entri cache — Laravel menyebut mekanisme penyimpanan tersebut cache driver, dan pilihannya ada tujuh. Pilihan driver menentukan kecepatan baca-tulis, ketahanan data terhadap restart server, dan bagaimana aplikasi menskalakan saat berjalan di beberapa server. Pada chapter ini kita bedah setiap driver, cara berganti di antara mereka, dan bagaimana satu aplikasi bisa memakai beberapa store sekaligus.
CACHE_STORE sebagai Pintu Depan #
Sama seperti session, driver cache dipilih lewat satu variabel lingkungan. File .env hasil laravel new langsung berisi baris berikut, karena sejak Laravel 11 nilai default-nya adalah database:
CACHE_STORE=databaseNilai tersebut dibaca config/cache.php sebagai store bawaan yang dipakai Cache facade setiap kali kita tidak menyebut store secara eksplisit. Perintah artisan berikut membuktikan store database aktif di sandbox dan bisa dikosongkan sepenuhnya:
$ php artisan cache:clear
INFO Application cache cleared successfully.Peta Tujuh Driver Cache #
Berikut perbandingan driver yang tersedia di config/cache.php beserta karakternya:
| Driver | Lokasi data | Kecepatan | Catatan penting |
|---|---|---|---|
database | Tabel cache | Sedang | Default Laravel 11+; butuh migrasi bawaan |
file | storage/framework/cache/data | Cepat (disk lokal) | Tanpa infrastruktur tambahan; satu server saja |
redis | Memori server Redis | Sangat cepat | Standar trafik besar; butuh server Redis |
memcached | Memori | Sangat cepat | Alternatif Redis; butuh server Memcached |
dynamodb | Layanan AWS | Cepat | Butuh kredensial AWS |
apc | Memori proses PHP (APCu) | Sangat cepat | Terbatas per server; tidak di config bawaan |
array | Memori proses PHP | - | Khusus testing; mati saat request selesai |
Perbedaan paling menentukan bukan kecepatan, melainkan berbagi: file dan apc hanya terlihat oleh satu server, sedangkan redis/memcached/dynamodb bisa dibaca semua server aplikasi. Ketika load balancer membagi request Budi ke server A dan Siti ke server B, hanya driver berbagi yang membuat entri cache tetap konsisten.
Satu Aplikasi, Banyak Store #
Kita tidak terikat pada satu pilihan. Method Cache::store() mengambil repository untuk store bernama, dan tiap store punya ruang kunci terpisah. Runner berikut menulis kunci yang sama ke tiga store berbeda:
use Illuminate\Support\Facades\Cache;
Cache::store('array')->put('kota', 'di array', 300);
Cache::store('database')->put('kota', 'di database', 300);
echo 'array=' . Cache::store('array')->get('kota')
. ' database=' . Cache::store('database')->get('kota') . "\n";
echo 'default=' . Cache::get('kota') . "\n";Output yang Dihasilkan:
array=di array database=di database
default=di databaseBaris terakhir membuktikan facade memakai store default dari CACHE_STORE, yaitu database. Driver file juga bisa diuji tanpa konfigurasi apa pun — entri ditulis sebagai file berisi timestamp kedaluwarsa dan nilai ter-serialize:
use Illuminate\Support\Facades\Cache;
$file = Cache::store('file');
$file->forget('kota');
$file->put('kota', 'Bandung', 300);
$path = storage_path('framework/cache/data');
$files = array_values(array_filter(
iterator_to_array(new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS))),
fn ($f) => $f->getExtension() !== 'gitignore',
));
echo 'jumlah_file=' . count($files)
. ' isi_file=' . substr(file_get_contents($files[0]->getPathname()), 0, 26) . "\n";
echo 'get_dari_file=' . $file->get('kota') . "\n";Output yang Dihasilkan:
jumlah_file=1 isi_file=1767261900s:7:"Bandung";
get_dari_file=BandungSatu kunci menghasilkan tepat satu file di dalam direktori storage/framework/cache/data (nama file adalah hash dari kunci). Isi file adalah gabungan timestamp kedaluwarsa 1767261900 dan nilai s:7:"Bandung"; yang ter-serialize — format yang persis sama dengan kolom tabel cache dari chapter sebelumnya.
Driver array untuk Testing #
phpunit.xml bawaan Laravel sudah menyetel CACHE_STORE=array khusus lingkungan testing. Ada dua alasan kuat untuk itu. Pertama, tanpa disk maupun query database, test berjalan lebih cepat. Kedua, memori proses mati bersama tiap test sehingga entri cache dari test yang satu tidak pernah bocor ke test berikutnya.
Migrasi Tabel cache #
Driver database menyimpan entri di tabel cache yang dibuat migrasi bawaan 0001_01_01_000001_create_cache_table.php:
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->primary();
$table->mediumText('value');
$table->bigInteger('expiration')->index();
});Perintah cache:table tersedia untuk aplikasi lama yang belum memilikinya. Di sandbox kita perintah ini menolak dengan jujur karena migrasinya sudah ada sejak awal:
$ php artisan cache:table
ERROR Migration already exists.Selain tabel cache, migrasi yang sama juga membuat cache_locks — tabel khusus untuk atomic lock, bahasan lanjutan di luar section ini.
Redis: phpredis atau predis #
Driver redis berbicara ke server Redis lewat salah satu dari dua jalan: ekstensi phpredis pada binary PHP (yang terpasang di sandbox ini), atau package predis/predis yang murni PHP melalui composer require predis/predis. Keduanya setara secara fitur; phpredis sedikit lebih cepat karena ditulis sebagai ekstensi C. Sandbox kita tidak menjalankan server Redis, sehingga operasi nyata gagal dengan pesan yang jujur:
RedisException: Connection refusedSetelah server Redis tersedia, koneksi diatur di config/database.php bagian redis, lalu store cache memakainya lewat REDIS_CACHE_CONNECTION di .env.
Prefix untuk Kunci #
Ketika beberapa aplikasi berbagi satu server Redis atau satu database, kunci kota dari aplikasi A bisa bertabrakan dengan kunci kota dari aplikasi B. CACHE_PREFIX mencegahnya — Laravel menyusun prefix dari nama aplikasi:
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
DB::table('cache')->delete();
Cache::put('kota', 'prefix bawaan', 300);
config(['cache.prefix' => 'myapp-cache-']);
Cache::forgetDriver(); // paksa manager membangun ulang store
Cache::put('kota', 'prefix baru', 300);
echo 'kunci_db=' . json_encode(
DB::table('cache')->where('key', 'like', '%kota')->pluck('key')->all()
) . "\n";Output yang Dihasilkan:
kunci_db=["laravel-cache-kota","myapp-cache-kota"]Dua entri kini hidup berdampingan di tabel yang sama dengan prefix berbeda — laravel-cache- berasal dari APP_NAME=Laravel. Panggilan forgetDriver() diperlukan karena cache manager menyimpan store yang sudah dibangun; tanpa panggilan tersebut, perubahan cache.prefix di tengah proses tidak akan terbaca. Daftar lengkap opsi konfigurasinya tersedia di dokumentasi Cache
.
Dengan driver dipilih, kita tinggal mengoperasikan cache-nya: menyimpan, membaca, menghapus, dan pola remember() yang merangkai semuanya — materi chapter Cache Operations
.