Writing Service Providers

Service Providers showed every register() finishing before any boot(), hence the rule: register() only binds, and boot() does the rest (listeners, view composers, gates, macros). A provider that only binds can be deferred:

app/Providers/PaymentServiceProvider.php (imports omitted)PHP
class PaymentServiceProvider extends ServiceProvider implements DeferrableProvider
{
    public array $singletons = [PaymentGateway::class => FakeGateway::class];
    public function provides(): array
    {
        return [PaymentGateway::class];
    }
}

provides() lands in bootstrap/cache/services.php, and the provider is not even constructed until something asks for PaymentGateway. A route that checks app()->getLoadedProviders() before and after app(PaymentGateway::class) returned:

Output of 192
$ curl -s http://127.0.0.1:8000/providers
before make(): deferred; after make(): loaded

Deferral helps only on web requests: the console kernel calls loadDeferredProviders() at bootstrap, so artisan and tinker load every provider first. Packages list providers under extra.laravel.providers, which package:discover loads automatically.