Aplikasi Laravel membaca konfigurasi dari banyak tempat: berkas PHP di config/, nilai di .env, cache di bootstrap/cache/. Tanpa disiplin, nilai-nilai ini menyebar ke mana-mana. Configuration management menutupnya dengan satu aturan sentral: config/ adalah satu-satunya jembatan antara environment dan kode aplikasi. Chapter ini membangun berkas konfigurasi sendiri, membuktikan kenapa env() tidak boleh dipanggil di luar config/, dan mendemokan bug klasik saat production mengaktifkan config:cache.
config/ sebagai Sumber Tunggal #
Aturannya satu kalimat: fungsi env() hanya boleh hidup di dalam berkas config/*.php. Seluruh kode aplikasi — controller, action, service, blade — membaca konfigurasi lewat config('kunci.nilai'). Ada tiga alasan. Pertama, config() menerima nilai default sehingga pemanggil tidak mengulang default yang sama di sepuluh tempat. Kedua, seluruh konfigurasi bisa dibekukan menjadi satu berkas cache untuk production. Ketiga, berkas config/ adalah dokumentasi hidup — membuka satu berkas langsung menunjukkan semua nilai yang bisa diatur beserta defaultnya.
Membuat Berkas Konfigurasi Sendiri #
Aplikasi kedai kopi kita punya beberapa kebijakan yang berubah antar lingkungan. Kita tuangkan ke config/kopi.php:
<?php
// config/kopi.php
return [
'nama' => env('KOPI_NAMA', 'Kedai Kopi Kita'),
'pajak' => (float) env('KOPI_PAJAK', 0.1),
'poin' => (int) env('KOPI_POIN', 10),
'mode' => env('KOPI_MODE', 'reguler'),
'fitur_lokal' => env('KOPI_FITUR_LOKAL', false),
'pengiriman' => [
'kota' => env('KOPI_KOTA', 'Jakarta'),
'ongkir' => (int) env('KOPI_ONGKIR', 10000),
],
];Semua panggilan env() dalam aplikasi ini kini hidup di satu berkas. Nilai KOPI_NAMA sampai KOPI_KOTA kita tambahkan ke .env, dan kode aplikasi memanggil config('kopi.nama') atau config('kopi.pengiriman.kota') untuk kunci bersarang. Untuk mengintip isinya tanpa membuka berkas, artisan menyediakan config:show:
Output yang Dihasilkan:
$ php artisan config:show kopi
kopi .......................................................................
nama ....................................................... Kedai Kopi Kita
pajak ................................................................. 0.11
poin .................................................................... 15
mode ............................................................... reguler
fitur_lokal .......................................................... false
pengiriman ⇁ kota .................................................. Bandung
pengiriman ⇁ ongkir .................................................. 10000config() dengan Nilai Default #
Pola aksesnya selalu dot notation dengan default sebagai argumen kedua. Sembilan var_dump pada berkas konfigurasi di atas menghasilkan:
Output yang Dihasilkan:
string(15) "Kedai Kopi Kita"
float(0.11)
int(15)
string(7) "reguler"
bool(false)
string(7) "Bandung"
int(10000)
NULL
string(7) "standar"Baris pertama sampai ketujuh berasal dari konfigurasi; dua baris terakhir menunjukkan perilaku kunci yang tidak ada: tanpa default hasilnya NULL, dengan default 'standar' hasilnya string fallback. Kombinasi casting eksplisit dan nilai default inilah yang membuat tipe hasil selalu bisa diprediksi — pajak selalu float, ongkir selalu integer, berapa pun bentuk nilainya di .env.
Jebakan Boolean pada env() #
Bagian yang menipu: nilai boolean. Laravel mengubah teks 'true' dan 'false' menjadi boolean sungguhan — tetapi hanya itu. Nilai lain seperti 'off', 'no', atau '1' tetap berupa string, dan string 'off' adalah truthy di PHP. Kita buktikan dengan menyuntikkan variabel environment asli seperti yang dilakukan orchestrator CI:
Output yang Dihasilkan:
string(3) "off"
bool(true)
string(3) "off"
bool(false)Baris kedua adalah bencananya: (bool) env('KOPI_FITUR_LOKAL') mengembalikan true padahal maksud penulis konfigurasi jelas-jelas “matikan”; nilai 'off' bahkan bocor sampai ke config('kopi.fitur_lokal') di baris ketiga. Baris keempat menunjukkan penawarnya — filter_var($nilai, FILTER_VALIDATE_BOOL) memahami 'off', 'no', '0', dan 'false' sekaligus.
.env, .env.testing, dan Berkas per Stage #
Laravel memilih berkas environment berdasarkan APP_ENV: saat menjalankan PHPUnit, phpunit.xml sudah menetapkan APP_ENV=testing, dan jika .env.testing ada, berkas itulah yang dimuat menggantikan .env — bukan ditumpuk di atasnya. Kita salin .env ke .env.testing dengan satu nilai berbeda: KOPI_POIN=25 (di .env nilainya 15). Satu test membuktikan pergantiannya benar-benar terjadi:
<?php
// tests/Feature/EnvTestingTest.php
public function test_dotenv_testing_digunakan_saat_phpunit(): void
{
$this->assertSame(25, config('kopi.poin'));
}Untuk stage lain, opsi --env memilih berkas serupa saat menjalankan artisan: .env.staging kita berisi KOPI_POIN=30, dan config:show mengonfirmasi pergantiannya:
Output yang Dihasilkan:
$ php artisan config:show kopi --env=staging
kopi .......................................................................
nama ....................................................... Kedai Kopi Kita
pajak ................................................................. 0.11
poin .................................................................... 30Semua berkas .env* berisi kredensial, jadi seluruhnya berstatus gitignore dan tidak pernah masuk repository — aturan rinci soal rahasia sudah kita bahas di chapter Secret Management
, sementara rujukan resmi seluruh mekanisme ini ada di dokumentasi configuration
.
config:cache dan Bug Klasik env() #
Di production, praktik standarnya membekukan seluruh konfigurasi: php artisan config:cache menghasilkan bootstrap/cache/config.php berisi array PHP seluruh konfigurasi aplikasi — berkas 22 KB pada sandbox ini, menyimpan 'poin' => 15 di baris ke-539 bersama ratusan kunci lain. Sejak berkas itu ada, Laravel berhenti memuat .env sama sekali. Inilah pangkal bug klasiknya — kode yang memanggil env() di luar config/ kehilangan sumber datanya:
Output yang Dihasilkan:
NULL
int(15)
NULL
string(15) "Kedai Kopi Kita"Dua baris pertama: env('KOPI_POIN') mengembalikan NULL sedangkan config('kopi.poin') tetap 15; dua baris berikutnya mengulang pola yang sama pada KOPI_NAMA. Karena test kita menguji lewat config() dan phpunit.xml menyuntikkan nilai environment asli, suite test bisa hijau sementara production diam-diam rusak. Kembalikan ke normal lewat php artisan config:clear; detail optimalisasi production-nya dibahas di chapter Config Cache
.
Konfigurasi kini terpusat dan aman di mode cache. Kita beralih ke kode yang terlihat setiap hari: controller yang perlahan menumpuk lemak, dan cara menurunkan beratnya bertahap.