> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Deferred Service Provider

> Wie Sie durch Implementierung des Interfaces DeferrableProvider Services verzögert laden. Ein unauffälliges, aber wichtiges Feature für die Performance von Paketen.

Beim Start von Laravel werden registrierte Service Provider auch dann geladen, wenn deren Funktionalität während einer Anfrage nie genutzt wird. Deferred Service Provider lösen dieses Problem, indem sie das Laden bis zur tatsächlichen Nutzung des Services aufschieben.

<Info>
  Diese Seite setzt Wissen aus [Grundlagen der Paketentwicklung](/de/advanced/package-development) voraus. Es empfiehlt sich, zunächst die grundlegende Funktionsweise von Service Providern zu verstehen.
</Info>

## Warum Deferred Provider nötig sind

Ein gewöhnlicher Service Provider ruft bei jeder Anfrage `register()` und `boot()` auf. Es ist Verschwendung, Funktionen wie Mail-Versand, Queue oder Cache jedes Mal zu initialisieren, obwohl sie auf vielen Seiten gar nicht gebraucht werden.

```php theme={null}
// Für diesen Provider wird bei jedem Request register() aufgerufen
class ReportServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        // Bindet den schwergewichtigen Report-Service jedes Mal
        $this->app->singleton(ReportGenerator::class, function ($app) {
            return new ReportGenerator(
                $app->make(PdfRenderer::class),
                $app->make(ChartRenderer::class),
                $app->make(DataExporter::class),
            );
        });
    }
}
```

Wenn Sie diesen Provider deferren, wird er nur bei Anfragen initialisiert, die tatsächlich einen Report erzeugen.

***

## Das Interface DeferrableProvider

`Illuminate\Contracts\Support\DeferrableProvider` ist ein schlichtes Interface mit einer einzigen Methode `provides()`.

```php theme={null}
namespace Illuminate\Contracts\Support;

interface DeferrableProvider
{
    public function provides();
}
```

Sobald Sie dieses Interface implementieren, arbeitet Ihr Provider im Deferred-Modus.

***

## Grundlegende Implementierung

Die Implementierung erfolgt in drei Schritten.

<Steps>
  <Step title="DeferrableProvider implementieren">
    ```php theme={null}
    use Illuminate\Contracts\Support\DeferrableProvider;
    use Illuminate\Support\ServiceProvider;

    class ReportServiceProvider extends ServiceProvider implements DeferrableProvider
    {
        // ...
    }
    ```
  </Step>

  <Step title="Services in register() binden">
    Bindungen tragen Sie wie in einem normalen Provider in `register()` ein.

    ```php theme={null}
    public function register(): void
    {
        $this->app->singleton(ReportGenerator::class, function ($app) {
            return new ReportGenerator(
                $app->make(PdfRenderer::class),
                $app->make(ChartRenderer::class),
                $app->make(DataExporter::class),
            );
        });

        $this->app->singleton(ReportRepository::class, function ($app) {
            return new ReportRepository($app->make('db'));
        });
    }
    ```
  </Step>

  <Step title="Aus provides() die registrierten Services zurückgeben">
    `provides()` muss **alle** Services zurückgeben, die Sie in `register()` gebunden haben. Laravel bestimmt anhand dieser Liste, „bei welchem Service dieser Provider zu laden ist".

    ```php theme={null}
    public function provides(): array
    {
        return [
            ReportGenerator::class,
            ReportRepository::class,
        ];
    }
    ```
  </Step>
</Steps>

***

## Funktionsweise des Service-Manifests

Beim Start erzeugt Laravel eine Manifest-Datei `bootstrap/cache/services.php`. Dort ist die Liste der Services aller Deferred Provider hinterlegt.

```php theme={null}
// Beispiel bootstrap/cache/services.php (automatisch generiert)
return [
    'providers' => [
        // Dieselbe Liste wie in bootstrap/providers.php
    ],
    'eager' => [
        // Sofort geladene Provider
        App\Providers\AppServiceProvider::class,
    ],
    'deferred' => [
        // Mapping Servicename => Provider-Klasse
        'App\Services\ReportGenerator' => ReportServiceProvider::class,
        'App\Repositories\ReportRepository' => ReportServiceProvider::class,
        'cache'     => Illuminate\Cache\CacheServiceProvider::class,
        'cache.store' => Illuminate\Cache\CacheServiceProvider::class,
        'queue'     => Illuminate\Queue\QueueServiceProvider::class,
    ],
    'when' => [],
];
```

Anhand dieses Manifests weiß Laravel, „welcher Provider einen Service anbietet", ohne die Dateien selbst zu laden. Der tatsächliche Provider wird erst dann geladen, wenn der Service zum ersten Mal aufgelöst wird.

<Tip>
  Nach dem Hinzufügen oder Ändern eines Providers regenerieren Sie das Manifest.

  ```shell theme={null}
  php artisan optimize:clear
  # oder
  php artisan clear-compiled
  ```
</Tip>

### Ablauf der internen Verarbeitung

```mermaid theme={null}
sequenceDiagram
    participant App as Laravel<br>App
    participant Container as Service<br>Container
    participant Manifest as services.php<br>Manifest
    participant Provider as ReportService<br>Provider

    App->>Manifest: Beim Start Manifest laden
    Manifest-->>App: Liste der Deferred Services
    Note over App: Der Provider ist noch nicht geladen

    App->>Container: $app->make(ReportGenerator::class)
    Container->>Manifest: Ist es ein Deferred Service?
    Manifest-->>Container: ReportServiceProvider liefert ihn
    Container->>Provider: register() + boot() aufrufen
    Provider-->>Container: Bindings registrieren
    Container-->>App: Instanz des ReportGenerator zurückgeben
```

***

## Bedeutung der Methode provides()

Vergessen Sie einen Eintrag in `provides()`, wird der betroffene Service nie aufgelöst.

```php theme={null}
public function register(): void
{
    $this->app->singleton(ReportGenerator::class, fn ($app) => new ReportGenerator());

    // Zusätzliches Binding
    $this->app->singleton('report', fn ($app) => $app->make(ReportGenerator::class));
}

public function provides(): array
{
    return [
        ReportGenerator::class,
        'report',  // ← Auch bei String-Keys nicht vergessen
    ];
}
```

Auch wenn Sie die Properties `$bindings` / `$singletons` verwenden, listen Sie sie in `provides()` auf.

```php theme={null}
class AnalyticsServiceProvider extends ServiceProvider implements DeferrableProvider
{
    public $singletons = [
        AnalyticsClient::class => DefaultAnalyticsClient::class,
    ];

    public function provides(): array
    {
        // Alle Keys aus $singletons wiederholen
        return [
            AnalyticsClient::class,
        ];
    }
}
```

***

## Grenzen von Deferred Providern

Deferred Provider eignen sich für Provider, die **ausschließlich Bindings im Container** registrieren. Provider, die in `boot()` z. B. Folgendes machen, dürfen nicht deferred werden.

| Einschränkung                                          | Grund                                                                                   |
| ------------------------------------------------------ | --------------------------------------------------------------------------------------- |
| Route-Registrierung                                    | Routen werden beim Anwendungsstart aufgelöst — im Deferred-Modus funktioniert das nicht |
| Registrierung globaler Middleware                      | Muss vor der Request-Verarbeitung erfolgen                                              |
| Registrierung von Event-Listenern (dauerhaft benötigt) | Muss vor dem Event feuern registriert sein                                              |
| Hinzufügen von Blade-Direktiven                        | Muss vor dem Kompilieren der Views erfolgen                                             |

<Warning>
  Sie dürfen bei Deferred Providern zwar eine `boot()`-Methode schreiben, aber deren Inhalt läuft erst, wenn der Service aufgelöst wird. Erledigen Sie in `boot()` „stets erforderliche" Aufgaben wie Routen oder Middleware, kommt es zu unerwartetem Verhalten.
</Warning>

***

## when() — Registrierung per Event-Trigger

Mit der Methode `when()` können Sie den Provider laden lassen, sobald ein bestimmtes Event feuert. Praktisch für Provider, die nur in bestimmten Kontexten (z. B. Job-Verarbeitung) benötigt werden.

```php theme={null}
class ReportServiceProvider extends ServiceProvider implements DeferrableProvider
{
    public function register(): void
    {
        $this->app->singleton(ReportGenerator::class, fn () => new ReportGenerator());
    }

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

    /**
     * Nicht nur beim Auflösen eines Services,
     * sondern auch beim Feuern bestimmter Events wird der Provider geladen.
     */
    public function when(): array
    {
        return [
            \App\Events\ReportRequested::class,
        ];
    }
}
```

Feuert eines der zurückgegebenen Events, wird der Provider geladen — auch wenn der Service noch nicht aufgelöst wurde.

***

## Nutzen in der Paketentwicklung

Auch bei Drittanbieter-Paketen tragen Deferred Provider zur Performance der Nutzer-Anwendung bei.

### Empfohlenes Muster

```php theme={null}
namespace Acme\Analytics;

use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;

class AnalyticsServiceProvider extends ServiceProvider implements DeferrableProvider
{
    public function register(): void
    {
        $this->mergeConfigFrom(__DIR__.'/../config/analytics.php', 'analytics');

        $this->app->singleton(AnalyticsManager::class, function ($app) {
            return new AnalyticsManager($app->make('config')->get('analytics'));
        });

        $this->app->singleton('analytics', fn ($app) => $app->make(AnalyticsManager::class));
    }

    public function boot(): void
    {
        // boot() nur für Publish-Registrierungen nutzen
        if ($this->app->runningInConsole()) {
            $this->publishes([
                __DIR__.'/../config/analytics.php' => config_path('analytics.php'),
            ], 'analytics-config');
        }
    }

    public function provides(): array
    {
        return [
            AnalyticsManager::class,
            'analytics',
        ];
    }
}
```

<Info>
  `mergeConfigFrom()` prüft intern, ob die Konfiguration gecacht ist. Der Aufruf innerhalb von `register()` eines Deferred Providers ist daher sicher. Bei gecachter Konfiguration passiert allerdings nichts.
</Info>

### Artisan-Commands mit `runningInConsole()` abtrennen

Command-Registrierung ist nur beim Artisan-Start nötig — trennen Sie sie mit `runningInConsole()`. Wenn Sie einen Provider deferren, der Commands anbietet, listen Sie die Command-Klassen auch in `provides()` oder stellen Sie einen separaten Command-Provider bereit.

```php theme={null}
public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->commands([
            AnalyticsFlushCommand::class,
        ]);
    }
}
```

***

## Verwendung im Laravel-Kern

Viele der Kern-Provider von Laravel sind Deferred Provider. So werden Services, die nicht bei jedem Request gebraucht werden, nicht sofort geladen.

| Provider                     | Bereitgestellte Services                |
| ---------------------------- | --------------------------------------- |
| `CacheServiceProvider`       | `cache`, `cache.store`, `RateLimiter`   |
| `QueueServiceProvider`       | `queue`, `queue.worker`, `queue.failer` |
| `MailServiceProvider`        | `mail.manager`, `mailer`                |
| `RedisServiceProvider`       | `redis`, `redis.connection`             |
| `HashServiceProvider`        | `hash`, `hash.driver`                   |
| `ValidationServiceProvider`  | `validator`, `validation.presence`      |
| `TranslationServiceProvider` | `translator`                            |
| `BroadcastServiceProvider`   | `Broadcast`                             |

In reinen API-Anwendungen kommt es vor, dass `MailServiceProvider` oder `BroadcastServiceProvider` während eines Requests nie geladen werden.

***

## Entscheidungskriterien für Deferring

<AccordionGroup>
  <Accordion title="Services, die sich zum Deferring eignen">
    * Services, die nicht in jedem Request genutzt werden (Mail, Reports, externe API-Clients)
    * Services, deren Initialisierung externe Verbindungen oder Dateizugriffe erfordert
    * Services mit schweren Objekt-Graphen
    * Provider, die nur in der CLI verwendete Commands liefern
  </Accordion>

  <Accordion title="Services, die sich nicht zum Deferring eignen">
    * Provider, die Routen registrieren (`loadRoutesFrom` usw.)
    * Provider, die dauerhaft aktive Middleware oder Exception-Handler registrieren
    * Provider, die globale Eloquent-Scopes oder Observer registrieren
    * Leichte Services, die in den meisten Requests genutzt werden (Overhead des Deferrings überwiegt)
  </Accordion>
</AccordionGroup>

***

## Verwandte Seiten

<Columns cols={2}>
  <Card title="Grundlagen der Paketentwicklung" icon="box" href="/de/advanced/package-development">
    Erläutert die Entwicklung von Laravel-Paketen rund um Service Provider.
  </Card>

  <Card title="Versionskompatibilität von Paketen verwalten" icon="layers" href="/de/advanced/package-versioning">
    Erläutert Wartungsstrategien für Pakete bei Major-Upgrades von Laravel und PHP.
  </Card>
</Columns>


## Related topics

- [Service-Provider](/de/service-providers.md)
- [FAQ zur neuen App-Struktur ab Laravel 11](/de/advanced/app-structure-faq.md)
- [Request-Lebenszyklus](/de/lifecycle.md)
- [Upgrade von Laravel 10 auf 11](/de/blog/upgrade-10-to-11.md)
- [Anwendungsstruktur ab Laravel 11](/de/advanced/app-structure.md)
