Service provider
Provider adalah satu-satunya tempat di Laravel yang berjalan sebelum apa pun terjadi. Yang perlu dipahami cuma satu hal: perbedaan antara register dan boot, dan kenapa mengabaikannya menghasilkan bug yang tidak konsisten.
Intisari
register()hanya mengikat ke container. Jangan memakai layanan lain di sini.boot()berjalan setelah semua provider ter-register โ di sinilah konfigurasi sesungguhnya dilakukan.- Provider didaftarkan di
bootstrap/providers.php. - Paket menemukan providernya sendiri lewat package discovery; kamu jarang perlu mendaftarkannya.
- Fase 8: di worker mode, kedua method ini hanya berjalan sekali seumur proses โ bukan tiap permintaan.
Dua method, dua aturan
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
// BOLEH: mengikat. Tidak ada yang dijalankan sekarang.
$this->app->singleton(GerbangPembayaran::class, MidtransGateway::class);
// JANGAN: memakai layanan lain. Provider yang menyediakannya mungkin
// belum ter-register saat baris ini dieksekusi.
// config('...') di sini masih berisiko; Route::, Gate::, View:: apalagi.
}
public function boot(): void
{
// Semua provider sudah ter-register. Di sini semuanya aman dipakai.
Model::preventLazyLoading(! app()->isProduction());
Model::unguard(false);
Gate::define('kelola-toko', fn (User $u) => $u->peran === 'admin');
Validator::extend('kode_pos_id', fn ($a, $v) => (bool) preg_match('/^\d{5}$/', $v));
View::share('namaToko', config('toko.nama'));
RateLimiter::for('api', fn (Request $r) =>
Limit::perMinute(60)->by($r->user()?->id ?: $r->ip()));
}
}
Kenapa aturan ini tidak boleh dilanggar. Bug yang dihasilkannya tidak konsisten: kodenya jalan hari
ini, lalu suatu hari kamu memasang paket baru, urutan pemuatan provider bergeser, dan tiba-tiba
register()-mu memakai layanan yang belum ada. Errornya muncul jauh dari penyebabnya.
register mengikat, boot memakai โ dua kata itu cukup.
Mendaftarkan provider
// bootstrap/providers.php
return [
App\Providers\AppServiceProvider::class,
App\Providers\TokoServiceProvider::class,
];
php artisan make:provider TokoServiceProvider # sekaligus mendaftarkannya
Paket pihak ketiga tidak perlu ditambahkan ke daftar ini. Composer mengumumkan providernya lewat blok
extra.laravel di composer.json paket tersebut, dan Laravel menemukannya sendiri โ
inilah kenapa composer require sebuah paket Laravel biasanya langsung bisa dipakai.
Apa yang layak tinggal di sini
| Urusan | Method | Contoh |
|---|---|---|
| Interface โ implementasi | register | bind(Gerbang::class, Midtrans::class) |
| Kebijakan model | boot | preventLazyLoading, shouldBeStrict |
| Aturan otorisasi global | boot | Gate::define(...) |
| Rate limiter bernama | boot | RateLimiter::for('api', ...) |
| Aturan validasi kustom | boot | Validator::extend(...) |
| Komponen Blade & direktif | boot | Blade::directive(...) |
| Pendengar event | boot | Event::listen(...) |
| Macro pada kelas framework | boot | Str::macro(...) |
Deferred provider
class LaporanServiceProvider extends ServiceProvider implements DeferrableProvider
{
public function register(): void
{
$this->app->singleton(MesinLaporan::class);
}
public function provides(): array
{
return [MesinLaporan::class]; // baru dimuat saat kelas ini benar-benar diminta
}
}
Provider yang di-defer tidak dimuat sampai layanannya dibutuhkan. Di mode PHP-FPM ini mengurangi biaya bootstrap setiap permintaan. Di worker mode manfaatnya mengecil โ bootstrap hanya sekali โ tapi tetap berguna untuk perintah Artisan yang tidak butuh separuh aplikasi.
Bacaan silang untuk Fase 8. Di Octane, register() dan boot() berjalan
satu kali saat worker menyala. Konsekuensinya: apa pun yang kamu baca dari $request di
dalam provider akan membeku pada permintaan pertama dan salah untuk semua permintaan berikutnya. Provider
tidak boleh tahu apa-apa tentang permintaan yang sedang berjalan.
Latihan: buat TokoServiceProvider yang mendefinisikan satu Gate, satu
View::share, dan satu Str::macro. Lalu sengaja pindahkan
Gate::define(...) ke register(), jalankan aplikasinya, dan baca errornya โ pengalaman
lima menit yang membuat aturan di atas melekat.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.