Service Providers

Where every part of Laravel is bootstrapped — register bindings, then boot behaviour.

Service providers are the central place all bootstrapping happens. Every framework feature — the database, the queue, routing — is wired up by a provider. Your own providers are where you register bindings, macros, view composers, policies and event listeners.

register() vs boot()

This distinction trips up a lot of people, and getting it right is a senior signal.

  • register() — ONLY bind things into the container. Do not resolve services here; other providers may not have registered theirs yet.
  • boot() — runs after all providers are registered. Safe to resolve and use anything. This is where you put macros, gates, event wiring.
public function register(): void
{
    $this->app->singleton(Weather::class, OpenWeather::class);
}

public function boot(): void
{
    // safe to touch other services here
    URL::forceScheme('https');
}

Deferred providers

If a provider only registers bindings (no boot work) you can implement DeferrableProvider so Laravel loads it lazily — only when one of its bindings is actually needed. A small but real boot-time win.

Example

Example · php
<?php

namespace App\Providers;

use App\Contracts\Weather;
use App\Services\OpenWeatherClient;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\Facades\{Gate, URL};
use Illuminate\Support\ServiceProvider;

class WeatherServiceProvider extends ServiceProvider implements DeferrableProvider
{
    /** register(): bindings ONLY — never resolve here. */
    public function register(): void
    {
        $this->app->singleton(Weather::class, function ($app) {
            return new OpenWeatherClient(config('services.weather.key'));
        });
    }

    /** boot(): runs after all providers registered — safe to use services. */
    public function boot(): void
    {
        if ($this->app->isProduction()) {
            URL::forceScheme('https');
        }
        Gate::define('view-forecast', fn ($user) => $user->subscribed());
    }

    /** Because this provider is deferrable, list what it provides. */
    public function provides(): array
    {
        return [Weather::class];
    }
}

When to use it

  • A developer creates a BillingServiceProvider that registers all payment-related bindings and boots billing-related observers, grouping related setup in one place.
  • A package author writes a service provider with a register() method so users can install the package and all its bindings are available after adding the provider to config/app.php.
  • A deferred provider registers expensive bindings only when they are actually resolved, reducing bootstrap time for requests that never use those services.

More examples

Create and register a service provider

Artisan generates the provider class; registering it in config/app.php makes Laravel boot it on every request.

Example · bash
php artisan make:provider BillingServiceProvider
# Then add to config/app.php 'providers' array:
# App\Providers\BillingServiceProvider::class

register() and boot() in a provider

register() runs during binding phase (no other services available yet); boot() runs after all providers are registered so it can safely call other services.

Example · php
class BillingServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        // Bind services — do NOT call other services here
        $this->app->singleton(BillingService::class, function ($app) {
            return new BillingService(
                config('billing.stripe_key'),
                $app->make(LoggerInterface::class)
            );
        });
    }

    public function boot(): void
    {
        // All providers are registered; safe to use services
        Order::observe(OrderObserver::class);
        View::share('currency', config('billing.currency'));
    }
}

Deferred service provider

Setting $defer = true prevents the provider from loading on every request; it bootstraps only when ReportGenerator is first resolved from the container.

Example · php
class ReportingServiceProvider extends ServiceProvider
{
    protected $defer = true;

    public function register(): void
    {
        $this->app->singleton(ReportGenerator::class, function () {
            return new ReportGenerator(config('reporting'));
        });
    }

    public function provides(): array
    {
        return [ReportGenerator::class];
    }
}

Discussion

  • Be the first to comment on this lesson.