Setelah route dibekukan, struktur berikutnya yang dibaca ulang di setiap permintaan adalah konfigurasi. Laravel menyimpan konfigurasi dalam belasan berkas PHP di folder config/, dan setiap berkas membaca nilai dari .env lewat env() saat dimuat. Tanpa cache, framework memindai folder itu, memuat berkas satu per satu, dan memanggil ratusan env() di setiap permintaan — pekerjaan yang hasilnya tidak pernah berubah selama deployment berlangsung. config:cache merangkum semuanya menjadi satu berkas array. Perintahnya sederhana; risikonya tersembunyi pada satu fungsi kecil bernama env(), dan melanggar aturannya menghadirkan bug yang hanya muncul di produksi.

Cara Config Dimuat Normalnya #

Sandbox kursus ini memiliki 11 berkas di folder config/:

text
app.php  auth.php  cache.php  database.php  filesystems.php  logging.php
mail.php  queue.php  sanctum.php  services.php  session.php

Saat bootstrap, setiap berkas di-require, seluruh array-nya digabung, dan hasilnya diserahkan ke repository config. Di dalamnya, puluhan pemanggilan env('DB_CONNECTION', 'sqlite') membaca variabel lingkungan dari .env. Proses ini cepat — berkas PHP murni tanpa parsing teks — tetapi tetap berupa kerja berulang yang identik di setiap permintaan, dan pada PHP-FPM setiap permintaan berarti proses yang baru memulai dari nol.

Membekukan Seluruh Config #

Perintahnya:

bash
php artisan config:cache

Output yang Dihasilkan:

text
INFO  Configuration cached successfully.

Hasilnya: berkas bootstrap/cache/config.php seukuran 22.411 byte pada sandbox kita. Seluruh konfigurasi — hasil akhir env() sudah dikunci nilainya — menjadi satu array PHP. Sepintas isinya seperti ini:

php
<?php return array (
  'hashing' =>
  array (
    'driver' => 'bcrypt',
    'bcrypt' =>
    array (
      'rounds' => '12',
      'verify' => true,
      // ...

Dua hal penting dari struktur ini. Pertama, nilai .env sudah terkunci menjadi konstanta — 'rounds' => '12' adalah hasil env('BCRYPT_ROUNDS', 12) yang dibekukan. Kedua, sesuai dokumentasi konfigurasi , saat berkas ini ada, Laravel tidak lagi memuat .env sama sekali. Konsekuensi dari fakta kedua inilah yang menjadi aturan emas bab ini.

Aturan Emas: env() Hanya di File Config #

Karena .env tidak dimuat saat config terkunci, setiap env() di luar file config akan mengembalikan null di produksi — padahal berjalan sempurna saat development. Kita buktikan bug klasik ini secara nyata. Asumsikan ada kode controller yang membaca nama aplikasi langsung dari environment:

php
$judul = env('APP_NAME'); // keliru: env() di kode aplikasi

Dengan config terkunci, kita jalankan:

php
use Illuminate\Support\Facades\App;

$app = require $dir.'/bootstrap/app.php';
App::getInstance()->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();

echo 'env("APP_NAME")    : ';
var_export(env('APP_NAME'));
echo "\n";
echo 'config("app.name"): ';
var_export(config('app.name'));
echo "\n";

Output yang Dihasilkan:

text
env("APP_NAME")    : NULL
config("app.name"): 'Laravel'

Persis seperti ramalannya: env() mengembalikan null karena .env tidak pernah dibaca, sementara config('app.name') menjawab 'Laravel' dari nilai yang dibekukan. Bug ini kejam karena tidak pernah terlihat di development (config tidak dikunci di sana) dan hanya muncul setelah deployment. Bandingkan dengan kondisi normal setelah cache dibersihkan:

bash
php artisan config:clear

Output yang Dihasilkan:

text
INFO  Configuration cache cleared successfully.

Setelah perintah itu, env('APP_NAME') kembali mengembalikan 'Laravel' — seolah-olah bugnya sembuh sendiri. Pola perbaikannya selalu sama: pindahkan pemanggilan env() ke file config sebagai nilai default, lalu kode aplikasi membaca lewat config():

php
// config/app.php
'name' => env('APP_NAME', 'Laravel'),

// kode aplikasi mana pun
$judul = config('app.name');

config:clear dan Ritual Deployment #

Seperti route cache, config cache membuat perubahan .env tidak berlaku sampai cache dibangun ulang. Mengubah DB_PASSWORD di .env lalu reload halaman tidak akan berpengaruh — aplikasi masih membaca nilai lama dari berkas beku. Ritual lengkapnya saat deployment:

bash
php artisan config:clear     # hapus cache lama (opsional, dihapus otomatis)
php artisan config:cache     # bekukan nilai .env terbaru
php artisan route:cache      # route setelah config — urutan ini dianjurkan

Untuk pipa deployment yang tidak mau menulis skrip panjang, Laravel menyediakan satu perintah pembungkus:

bash
php artisan optimize

Output yang Dihasilkan:

text
INFO  Caching framework bootstrap, configuration, and metadata.

config ......................................................... 6.61ms DONE
events ......................................................... 0.94ms DONE
routes ......................................................... 8.18ms DONE
views ......................................................... 35.29ms DONE

Perintah optimize membangun cache config, events, routes, dan views sekaligus — dan kebalikannya, optimize:clear, membersihkan semuanya:

bash
php artisan optimize:clear

Output yang Dihasilkan:

text
INFO  Clearing cached bootstrap files.

config ......................................................... 1.05ms DONE
cache ......................................................... 10.91ms DONE
compiled ....................................................... 0.56ms DONE
events ......................................................... 0.46ms DONE
routes ......................................................... 0.43ms DONE
views .......................................................... 3.42ms DONE

Perhatikan bahwa optimize menyertakan views di daftar kerjanya — baris views ... 35.29ms DONE mengompilasi seluruh template Blade. Layer ketiga dari trio cache inilah yang menjadi fokus chapter berikutnya: bagaimana Blade dikompilasi, dan mengapa prakompilasi di produksi menghapus hukuman bagi pengunjung pertama.