AppServiceProvider Essentials Configuration
Project ini menggunakan beberapa konfigurasi global di AppServiceProvider untuk meningkatkan performa, keamanan, pengalaman development, dan konsistensi perilaku aplikasi.
Dokumen ini saya sesuaikan langsung dengan isi app/Providers/AppServiceProvider.php, jadi bagian yang dijelaskan di sini mengikuti konfigurasi project yang benar-benar sedang dipakai.
Kenapa AppServiceProvider Penting
Banyak developer baru menganggap file ini hanya formalitas. Padahal justru di sinilah kita sering meletakkan aturan global seperti:
- bagaimana URL dibentuk
- bagaimana model Laravel berperilaku
- bagaimana database diproteksi
- bagaimana testing dibuat lebih aman
Kalau bagian ini dibiarkan tanpa arah, project cepat terasa inkonsisten.
Asset Prefetching
Vite::useAggressivePrefetching();
Tujuan
Membantu browser memuat asset lebih cepat saat user berpindah halaman.
Kenapa saya pakai ini
Untuk admin panel, perpindahan halaman sangat sering terjadi. Prefetching membantu UX terasa lebih cepat tanpa kita harus menulis optimasi frontend manual yang rumit.
Studi kasus
Bayangkan admin membuka daftar user, lalu pindah ke halaman edit, lalu ke role management. Dengan aggressive prefetching, sebagian asset sudah mulai disiapkan lebih awal.
Force HTTPS
URL::forceHttps();
Tujuan
Memastikan URL yang dihasilkan aplikasi menggunakan https://.
Catatan penting
Di project ini baris ini sedang aktif. Karena itu, jika Anda memakai Laravel Herd, pastikan site Anda dijadikan Secure Site. Kalau belum, URL bisa terasa aneh atau request tertentu bisa bermasalah.
Kalau Anda sedang development di environment yang belum siap HTTPS, Anda bisa mengomentari baris ini terlebih dahulu.
Studi kasus
Kalau aplikasi production Anda ada di balik SSL tetapi aplikasi masih menghasilkan URL http://, maka:
- link di email bisa salah
- asset URL bisa tidak konsisten
- redirect atau callback URL bisa membingungkan
Password Defaults (Opsional)
// Password::defaults(fn (): Password => app()->isProduction()
// ? Password::min(8)->uncompromised()->letters()->numbers()->symbols()
// : Password::min(8)
// );
Tujuan
Menetapkan standar password global dari satu tempat.
Status di project ini
Bagian ini masih dikomentari, jadi belum aktif.
Kenapa tetap saya simpan
Karena ini berguna saat project mulai membutuhkan standar password yang lebih ketat, terutama di production.
Strict Models (Opsional)
// Model::shouldBeStrict();
Tujuan
Membantu mendeteksi:
- lazy loading yang tidak sengaja
- atribut yang tidak valid
- beberapa perilaku model yang terlalu permisif
Status di project ini
Masih dikomentari. Cocok diaktifkan jika tim sudah siap dengan mode Eloquent yang lebih ketat.
Unguard Mass Assignment di Local
if (app()->isLocal()) {
Model::unguard();
}
Tujuan
Mematikan proteksi mass-assignment saat development lokal.
Kenapa saya pakai ini
Karena starter kit ini menggunakan Action Pattern, strict typing, dan alur mutasi data yang lebih terkontrol. Jadi di local, saya memilih fleksibilitas lebih tinggi untuk development.
Catatan penting
Ini hanya aktif saat app()->isLocal(). Jadi perilaku ini memang dibatasi untuk environment development.
Studi kasus
Saat Anda menulis seeder, factory, atau action baru, kadang lebih nyaman bekerja tanpa harus terus menyesuaikan $fillable. Selama struktur mutasi data tetap disiplin, pendekatan ini masih masuk akal.
Protect Destructive Commands
DB::prohibitDestructiveCommands(app()->isProduction());
Tujuan
Mencegah command database yang destruktif berjalan di production.
Contoh command berbahaya
migrate:freshdb:wipe- operasi hapus massal yang tidak semestinya dijalankan di server production
Cara pikir saya
Saya lebih suka proteksi seperti ini aktif dari awal daripada mengandalkan semua orang selalu ingat sedang ada di environment apa.
Handle Potentially Lost Transactions
DB::handlePotentiallyLostTransactions();
Tujuan
Membantu Laravel menangani situasi transaksi database yang berpotensi hilang atau gagal secara tidak ideal.
Kenapa ini penting
Saat aplikasi mulai kompleks, kita makin sering bergantung pada transaksi untuk menjaga integritas data. Fitur ini adalah bagian dari pendekatan defensif agar perilaku transaksi lebih aman.
Cara membayangkannya
Kalau DB::transaction() adalah pagar utama untuk menjaga beberapa perubahan tetap utuh, maka konfigurasi ini membantu Laravel lebih sadar ketika ada gangguan yang bisa membuat transaksi tidak berakhir seperti yang diharapkan.
Immutable Dates
Date::use(CarbonImmutable::class);
Tujuan
Menggunakan CarbonImmutable agar object tanggal tidak berubah tanpa sengaja.
Kenapa ini penting
Developer pemula sering tidak sadar bahwa manipulasi tanggal bisa mengubah object awal. Dengan immutable date, perubahan menjadi lebih eksplisit dan lebih aman diprediksi.
Automatically Eager Load Relationships
Model::automaticallyEagerLoadRelationships();
Tujuan
Membantu Laravel melakukan eager loading relasi secara otomatis.
Status di project ini
Bagian ini aktif di AppServiceProvider.
Kenapa saya nyalakan
Karena project admin panel sering menampilkan relasi berulang-ulang di banyak halaman. Fitur ini membantu mengurangi beberapa kasus N+1 query tanpa kita harus selalu mengingat eager loading manual di setiap tempat.
Catatan
Meski aktif, developer tetap perlu memahami query yang sedang berjalan. Fitur ini membantu, tetapi bukan pengganti pemahaman struktur data.
Testing: Prevent Stray HTTP Requests (Opsional)
// if (app()->runningUnitTests()) {
// Http::preventStrayRequests();
// }
Tujuan
Mencegah test secara tidak sengaja melakukan request HTTP keluar ke layanan eksternal.
Kenapa ini berguna
Saat menulis test, kita biasanya ingin semua dependency eksternal di-fake atau di-mock. Kalau tidak, test bisa:
- lambat
- tidak stabil
- tergantung koneksi internet
- diam-diam memanggil API sungguhan
Status di project ini
Masih dikomentari, tetapi sangat layak dipertimbangkan jika test suite makin banyak berhubungan dengan API eksternal.
Testing: Fake Sleep (Opsional)
// if (app()->runningUnitTests()) {
// Sleep::fake();
// }
Tujuan
Menonaktifkan jeda sleep saat testing agar test tetap cepat.
Kenapa ini berguna
Kadang ada flow retry, polling, atau throttling sederhana yang memakai sleep. Di production, jeda itu masuk akal. Di testing, jeda itu hanya membuat suite menjadi lambat.
Dengan Sleep::fake(), test tetap menjalankan alur logikanya tanpa benar-benar menunggu.
Studi kasus
Bayangkan Anda punya service yang mencoba ulang request 3 kali dan setiap percobaan memakai jeda 1 detik. Tanpa fake sleep, satu test bisa menunggu beberapa detik tanpa memberi nilai tambah. Dengan Sleep::fake(), test tetap memverifikasi flow retry tanpa membuang waktu nyata.
Studi Kasus Besar
Misalnya project Anda sudah dipakai tim internal:
- ada developer baru yang memakai Herd tapi belum mengaktifkan secure site
- ada action yang banyak memakai transaksi database
- ada halaman admin yang sering menampilkan relasi
- ada test yang berhubungan dengan API eksternal
- ada flow retry yang memakai sleep
Semua itu bisa dipengaruhi langsung oleh konfigurasi kecil di AppServiceProvider. Karena itu, file ini terlihat sederhana, tetapi dampaknya global.
Tips
- Gunakan
app()->isLocal(),app()->isProduction(), danapp()->runningUnitTests()untuk memisahkan perilaku per environment - Jangan aktifkan semua fitur hanya karena terlihat canggih; pahami dulu efek sampingnya
- Setelah mengubah
AppServiceProvider, uji flow utama aplikasi karena dampaknya bisa terasa ke banyak tempat