Variabel Environment
Package ini tidak mendefinisikan variabel environment miliknya sendiri. Setiap nilai di config/panda-panel.php bersifat literal — tidak ada satu pun pemanggilan env() di file tersebut maupun di dalam src/. Namun, behavior Panel tetap bergantung pada sejumlah konfigurasi Laravel standar, yang pada skeleton Laravel umumnya terhubung ke variabel environment. Halaman ini menjelaskan daftar konfigurasi tersebut dan pengaruh masing-masing terhadap Panel.
Contoh minimal yang berfungsi
Sebuah Panel tidak membutuhkan apa pun selain application Laravel yang sudah berjalan dengan benar:
APP_NAME="Acme"
APP_ENV=production
APP_DEBUG=false
APP_KEY=base64:…
DB_CONNECTION=…2
3
4
5
php artisan migrate
php artisan panel:cache2
Semua bagian berikut membahas feature Panel tertentu — realtime notification, queued export, kode two-factor melalui email — dan semuanya bersifat opsional.
Tidak ada konfigurasi di sini yang terikat langsung ke env
// config/panda-panel.php — the whole file's shape
'panels' => [],
'register_routes' => true,
'register_web_middleware' => true,
'register_guest_redirect' => true,
'home_redirect' => ['enabled' => true, 'paths' => ['dashboard']],
'load_migrations' => true,
'integrations' => [...],
'frontend' => ['panel_path' => 'js/panel', 'pages_path' => 'js/pages/Panels'],2
3
4
5
6
7
8
9
10
Ini disengaja. Lima konfigurasi tersebut dibaca satu kali saat boot untuk menentukan apakah framework mendaftarkan route, middleware, redirect, dan migration. Jika sebuah registration switch dapat menghasilkan nilai berbeda antara web request dan queue worker pada deployment yang sama, bug yang terjadi akan sangat sulit direproduksi. Jika Anda memang ingin nilainya berbeda berdasarkan environment, hubungkan sendiri di file config — karena di situlah env() dibaca sebelum config:cache membekukan konfigurasi.
// config/panda-panel.php
'register_guest_redirect' => env('PANEL_GUEST_REDIRECT', true),2
3
Pastikan tipenya benar. env() dapat menghasilkan string, sedangkan key seperti ini dibandingkan dengan === true. Jadi value string yang bukan boolean true akan menonaktifkan feature. Laravel memang mengonversi literal true dan false dari .env, tetapi value yang datang dari shell atau container orchestrator belum tentu melewati normalisasi yang sama.
Konfigurasi Laravel yang dibaca oleh Panel
| Feature | Config key | Env var pada skeleton default | Jika kosong atau salah |
|---|---|---|---|
| Nama brand Panel | app.name | APP_NAME | Brand fallback ke nilai config('app.name'). |
| Peringatan stale manifest | app.debug, app.env | APP_DEBUG, APP_ENV | Hanya dicatat ketika debug aktif atau environment local/testing. Sengaja silent di production. |
| Realtime toast dan notification bell | broadcasting.default, broadcasting.connections.*.driver | BROADCAST_CONNECTION | Prop broadcasting menjadi {enabled: false, channel: null} dan frontend tidak melakukan subscription. |
| Queued export, import, integration delivery, dan two-factor mail | queue.default | QUEUE_CONNECTION | Dengan sync, semuanya berjalan inline. Dengan connection queue sungguhan tetapi tanpa worker, job tidak pernah diproses dan tidak ada error pada request yang melakukan dispatch. |
| Kode two-factor melalui email serta send/guess limit | cache.default | CACHE_STORE | Kode hidup selama sepuluh menit di cache; cache flush membatalkan kode yang belum dipakai dan mereset rate limit. |
| Email berisi kode two-factor | mail.default | MAIL_MAILER | Kode tetap dibuat dan masuk cache, tetapi email tidak pernah sampai. |
| File export dan import | filesystems.disks.local | — | Exporter::disk() dan Importer::disk() mengembalikan 'local', yaitu nama disk, bukan FILESYSTEM_DISK. Override method tersebut jika ingin menggunakan disk lain. |
| Session Panel | session.* | SESSION_DRIVER, SESSION_DOMAIN | Panel berada di belakang middleware web; tanpa session tidak ada login dan setiap form akan gagal dengan 419. |
Broadcasting
PandaPanel\Support\BroadcastSupport::isConfigured() menentukan apakah prop broadcasting memiliki enabled: true — prop tersebut tetap dibagikan pada setiap request — dan melakukan tiga pemeriksaan:
BroadcastSupport::isConfigured(); // boolbroadcasting.defaultharus menunjuk ke sebuah connection.- Connection tersebut harus ada dan memiliki driver.
- Driver tidak boleh
nullataulog— keduanya memang driver yang valid, tetapi browser tidak dapat melakukan subscription terhadap keduanya.
Panel secara default menginginkan realtime karena broadcasting() aktif. Namun jika application tidak memiliki broadcaster yang benar-benar dapat digunakan browser, Panel mengirim enabled: false daripada mengirim channel yang tidak dapat digunakan. Pemeriksaan ini mencegah kegagalan yang lokasinya jauh dari penyebab sebenarnya: server mengirim channel, client memanggil echo(), @laravel/echo-vue melempar "Echo has not been configured" dari onMounted, lalu proses mount layout ikut gagal.
BROADCAST_CONNECTION=reverb
REVERB_APP_ID=…
REVERB_APP_KEY=…
REVERB_APP_SECRET=…
REVERB_HOST=localhost
REVERB_PORT=8080
REVERB_SCHEME=http
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"2
3
4
5
6
7
8
9
10
11
12
13
Credential sengaja tidak divalidasi oleh PandaBear. Hanya broadcaster yang dapat mengetahui apakah sebuah key benar. Menolak connection hanya karena format key terlihat aneh justru akan menghasilkan failure mode yang lebih buruk. Lihat Reverb and Echo.
Queues
PandaPanel\Jobs\RunPanelExport, RunPanelImport, dan SendPanelIntegration mengimplementasikan ShouldQueue, begitu juga notification TwoFactorCode. Broadcast event menggunakan ShouldBroadcast, bukan ShouldBroadcastNow, sehingga event tersebut juga masuk queue.
Dengan QUEUE_CONNECTION=sync, semuanya dijalankan inline. Inilah alasan realtime notification terlihat berfungsi di local tanpa worker, lalu seolah "berhenti" ketika queue diganti ke connection sungguhan. Lihat Queued Notifications dan Queued Exports.
URL Panel yang dibuat di dalam job tersebut bersifat relatif (route(..., absolute: false)), sehingga worker dengan APP_URL yang salah tidak otomatis menghasilkan link Panel yang rusak.
Environment pada frontend
Komponen yang dipublish hanya membaca dua hal dari environment Vite:
| Dibaca | Lokasi | Tujuan |
|---|---|---|
import.meta.env.DEV | registry icon, form, dan widget | Menampilkan warning di console hanya saat development ketika nama component tidak ada pada build-time allowlist |
import.meta.env.VITE_APP_NAME | dideklarasikan di resources/js/types/global.d.ts | Nama application, mengikuti pola starter kit |
Semua yang dirender screen Panel dikirim sebagai Inertia props dari server, sehingga tidak ada variabel seperti VITE_PANEL_*. Konfigurasi Echo berada di file application sendiri, resources/js/app.ts, yang tidak dipublish package:
import { configureEcho } from '@laravel/echo-vue';
configureEcho({ broadcaster: 'reverb' });2
3
configureEcho() hanya menyiapkan konfigurasi. Connection belum dibuka sampai ada component yang melakukan subscription. Karena itu $panel->broadcasting(false) benar-benar tidak membuka connection, bukan sekadar membuka connection lalu mengabaikannya.
Membaca environment value di dalam Panel
Gunakan config(), bukan env():
public function panel(Panel $panel): Panel
{
return $panel
->path((string) config('panels.admin_path', 'admin'))
->strictAuthorization(app()->environment('local', 'testing'));
}2
3
4
5
6
Setelah php artisan config:cache dijalankan, env() di luar file config dapat menghasilkan null. Jika path Panel dibaca langsung dari env(), Panel dapat terpasang pada path kosong di production tanpa error yang menjelaskan penyebabnya. Aturan yang sama berlaku untuk Resource, Page, Widget, dan code lain yang berjalan setelah boot.
File config adalah pengecualian, dan config/panda-panel.php memang merupakan file config:
// config/panda-panel.php
'panels' => array_values(array_filter([
App\Panels\Admin\AdminPanelProvider::class,
env('APP_ENV') === 'local' ? App\Panels\Debug\DebugPanelProvider::class : null,
])),2
3
4
5
6
Behavior yang sensitif terhadap environment
Ada tiga behavior package yang berubah mengikuti environment, dan ketiganya tidak configurable:
| Behavior | Aturan |
|---|---|
| Peringatan stale panel manifest | Hanya dicatat jika app()->hasDebugModeEnabled() atau environment local/testing. Di production, manifest dianggap sumber kebenaran dan filesystem tidak disentuh. |
| Warning registry di browser console | Hanya ketika import.meta.env.DEV. Production build tidak menampilkan warning. |
| Notice Policy yang hilang | Menggunakan Log::debug() dengan aturan environment yang sama, satu kali per model per process. Resource yang sengaja disembunyikan dari semua user adalah kondisi valid, sehingga log pada setiap deploy justru akan menjadi noise. Lihat Authorization. |
Hal yang perlu diperhatikan
env()diconfig/panda-panel.phpharus memiliki tipe yang benar. Setiap switch dibandingkan dengan=== true, sehingga string bukanlah booleantrue.config:cachetetap menangkap default package. Command melakukan boot application terlebih dahulu sebelum serialization, sehinggamergeConfigFrom()sudah berjalan dan config yang belum dipublish tetap masuk cache dengan default package.- Queue worker adalah process terpisah dengan environment terpisah. Export yang berhasil pada request tetapi gagal pada job biasanya berarti worker masih menggunakan
.envlama, atau disklocalmengarah ke root yang berbeda antara web process dan worker. CACHE_STORE=arraypada web process membuat kode email tidak dapat diverifikasi, karena store dibuat ulang setiap request. Ini tetap cocok untuk test yang seluruh flow-nya berjalan di satu process.SESSION_DOMAINperlu diputuskan secara eksplisit untuk Panel pada subdomain. Session cookie yang tidak mencakup host Panel akan membuat user terlihat logout ketika berpindah masuk ke Panel. Lihat Tenant URLs.- Tidak ada environment variable
PANEL_*bawaan. Jika Anda mencari konfigurasi Panel di.env, sumbernya sebenarnya berada diconfig/panda-panel.phpdan Panel Provider.