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

# Service-Container

> Erfahren Sie, wie Dependency Injection mit dem Service-Container von Laravel funktioniert und wie Bindings grundsätzlich registriert werden.

## Was ist der Service-Container

Der Service-Container von Laravel ist ein Mechanismus zur Verwaltung von Klassenabhängigkeiten und zur Durchführung von Dependency Injection. Dependency Injection bedeutet, dass die von einer Klasse benötigten Abhängigkeiten über den Konstruktor oder gegebenenfalls über Setter-Methoden in die Klasse „injiziert" werden.

Sehen Sie sich das folgende Beispiel an:

```php theme={null}
<?php

namespace App\Http\Controllers;

use App\Services\AppleMusic;
use Illuminate\View\View;

class PodcastController extends Controller
{
    /**
     * Neue Controller-Instanz erzeugen
     */
    public function __construct(
        protected AppleMusic $apple,
    ) {}

    /**
     * Informationen zum angegebenen Podcast anzeigen
     */
    public function show(string $id): View
    {
        return view('podcasts.show', [
            'podcast' => $this->apple->findPodcast($id)
        ]);
    }
}
```

In diesem Beispiel muss der `PodcastController` einen Podcast von einer Datenquelle wie Apple Music beziehen. Dazu wird ein Dienst **injiziert**, der Podcasts abrufen kann. Durch das Injizieren des Dienstes lässt sich beim Testen ein Mock (eine Dummy-Implementierung) des `AppleMusic`-Dienstes leicht einsetzen.

<Info>
  Ein tiefes Verständnis des Service-Containers ist beim Aufbau großer Laravel-Anwendungen unerlässlich. Es hilft auch dabei, zum Laravel-Core selbst beizutragen.
</Info>

```mermaid theme={null}
flowchart TD
    A["Service-Provider<br>register()"] --> B["Service-Container<br>Binding registrieren"]
    B --> C{"Auflösungsanfrage<br>make() / Auto-Injection"}
    C -- "Konkrete Klasse" --> D["Automatische Auflösung<br>über Reflection"]
    C -- "Interface" --> E["Registrierte Implementierung<br>auflösen"]
    D --> F["Instanz erzeugen<br>in Konstruktor injizieren"]
    E --> F
```

## Zero-Configuration-Auflösung

Wenn eine Klasse nur von anderen konkreten Klassen (keinen Interfaces) abhängt, müssen Sie dem Container nicht mitteilen, wie sie aufzulösen ist. Nehmen Sie zum Beispiel folgenden Code in `routes/web.php` an:

```php theme={null}
<?php

class Service
{
    // ...
}

Route::get('/', function (Service $service) {
    dd($service::class);
});
```

<Info>
  In diesem Beispiel wird die Klasse innerhalb der Routendatei definiert – dies dient nur zu Demonstrationszwecken. In einer echten Anwendung sollten Service-Klassen im Verzeichnis `app/Services` definiert werden.
</Info>

Beim Aufruf dieser Route löst Laravel die `Service`-Klasse automatisch auf und injiziert sie in den Route-Handler. Sie profitieren also von Dependency Injection, ohne eine Konfigurationsdatei anlegen zu müssen.

Bei vielen Klassen, die Sie in einer Laravel-Anwendung schreiben – etwa Controller, Event-Listener oder Middleware – werden Abhängigkeiten automatisch über den Container injiziert.

## Bindings

### Einfache Bindings

Die meisten Bindings werden innerhalb von [Service-Providern](/de/service-providers) registriert. In einem Service-Provider können Sie über die Eigenschaft `$this->app` auf den Container zugreifen.

#### bind

Mit der `bind`-Methode registrieren Sie ein Binding, indem Sie einen Klassen- oder Interface-Namen zusammen mit einer Closure übergeben:

```php theme={null}
use App\Services\Transistor;
use App\Services\PodcastParser;
use Illuminate\Contracts\Foundation\Application;

$this->app->bind(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});
```

Die Closure erhält als Argument den Container selbst und kann darüber Unterabhängigkeiten auflösen.

Wenn Sie den Container außerhalb eines Service-Providers verwenden möchten, nutzen Sie die `App`-Fassade:

```php theme={null}
use App\Services\Transistor;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\App;

App::bind(Transistor::class, function (Application $app) {
    // ...
});
```

<Info>
  Klassen, die nicht von einem Interface abhängen, müssen nicht an den Container gebunden werden. Der Container kann solche Objekte automatisch über Reflection auflösen.
</Info>

#### singleton

Die `singleton`-Methode bindet eine Klasse oder ein Interface so, dass sie nur ein einziges Mal aufgelöst wird. Ist ein Singleton einmal aufgelöst, gibt der Container bei jedem weiteren Aufruf dieselbe Instanz zurück.

```php theme={null}
use App\Services\Transistor;
use App\Services\PodcastParser;
use Illuminate\Contracts\Foundation\Application;

$this->app->singleton(Transistor::class, function (Application $app) {
    return new Transistor($app->make(PodcastParser::class));
});
```

#### instance

Eine bereits existierende Objektinstanz können Sie über die `instance`-Methode an den Container binden. Bei nachfolgenden Aufrufen des Containers wird stets diese Instanz zurückgegeben.

```php theme={null}
use App\Services\Transistor;
use App\Services\PodcastParser;

$service = new Transistor(new PodcastParser);

$this->app->instance(Transistor::class, $service);
```

### Interfaces an Implementierungen binden

Eine der leistungsstärksten Funktionen des Service-Containers ist die Möglichkeit, ein Interface an eine bestimmte Implementierung zu binden. Angenommen, es existiert das Interface `EventPusher` und die Implementierung `RedisEventPusher`:

```php theme={null}
use App\Contracts\EventPusher;
use App\Services\RedisEventPusher;

$this->app->bind(EventPusher::class, RedisEventPusher::class);
```

Dadurch injiziert der Container in jede Klasse, die eine Implementierung von `EventPusher` benötigt, den `RedisEventPusher`. Sie müssen dann lediglich das Interface `EventPusher` als Type-Hint im Konstruktor angeben:

```php theme={null}
use App\Contracts\EventPusher;

/**
 * Neue Klasseninstanz erzeugen
 */
public function __construct(
    protected EventPusher $pusher,
) {}
```

<Tip>
  Wenn Sie von Interfaces abhängen, müssen Sie Ihren Code nicht anpassen, wenn Sie die Implementierung austauschen. Das erleichtert das Testen und spätere Änderungen erheblich.
</Tip>

## Automatische Auflösung (DI per Type-Hint)

Wenn der Service-Container Klassen wie Controller, Event-Listener oder Middleware auflöst, berücksichtigt er die Type-Hints des Konstruktors und injiziert die Abhängigkeiten automatisch.

```php theme={null}
<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;

class UserController extends Controller
{
    /**
     * Neue Controller-Instanz erzeugen
     */
    public function __construct(
        protected UserRepository $users,
    ) {}
}
```

Solange `UserRepository` nicht von einem Interface abhängt, ist keine Registrierung im Container notwendig. Sobald die entsprechende Route aufgerufen wird, löst der Container die Abhängigkeit automatisch auf und injiziert sie in den Controller.

## Auflösen aus dem Container

### Methode `make`

Mit der `make`-Methode können Sie eine Klasseninstanz aus dem Container auflösen:

```php theme={null}
use App\Services\Transistor;

$transistor = app()->make(Transistor::class);
```

Falls Abhängigkeiten der Klasse nicht vom Container aufgelöst werden können, lassen sich über die Methode `makeWith` zusätzliche Argumente übergeben:

```php theme={null}
$transistor = $this->app->makeWith(Transistor::class, ['id' => 1]);
```

### Automatische Injection

In der Praxis rufen Sie die `make`-Methode selten direkt auf. Bei Klassen, die vom Container aufgelöst werden – etwa Controller, Event-Listener oder Middleware – reicht es aus, Type-Hints im Konstruktor anzugeben; der Container übernimmt die Injection dann automatisch.

## Fassaden und der Container

Die Fassaden von Laravel bieten eine statische Schnittstelle zu Objekten im Container. So ruft beispielsweise `Cache::get()` intern den `Cache`-Dienst aus dem Container ab und delegiert den Aufruf an ihn.

```php theme={null}
use Illuminate\Support\Facades\Cache;

// Aufruf über die Fassade
Cache::get('key');

// Äquivalenter Aufruf direkt über den Container
app('cache')->get('key');
```

Fassaden sind komfortable Wrapper um den Container. Beim Testen lassen sie sich außerdem durch Mocks ersetzen.

```php theme={null}
use Illuminate\Support\Facades\Cache;

Cache::shouldReceive('get')
    ->once()
    ->with('key')
    ->andReturn('value');
```

## Konstruktor-Injection – ein praktisches Beispiel

Betrachten wir ein typisches Muster aus einer realen Anwendung.

<Steps>
  <Step title="Interface definieren">
    ```php theme={null}
    <?php

    namespace App\Contracts;

    interface PaymentGateway
    {
        public function charge(int $amount, string $token): bool;
    }
    ```
  </Step>

  <Step title="Implementierung erstellen">
    ```php theme={null}
    <?php

    namespace App\Services;

    use App\Contracts\PaymentGateway;

    class StripePaymentGateway implements PaymentGateway
    {
        public function charge(int $amount, string $token): bool
        {
            // Zahlung über die Stripe-API abwickeln...
            return true;
        }
    }
    ```
  </Step>

  <Step title="Im Service-Provider binden">
    ```php theme={null}
    use App\Contracts\PaymentGateway;
    use App\Services\StripePaymentGateway;

    $this->app->singleton(PaymentGateway::class, StripePaymentGateway::class);
    ```
  </Step>

  <Step title="Injection im Controller entgegennehmen">
    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use App\Contracts\PaymentGateway;
    use Illuminate\Http\Request;

    class OrderController extends Controller
    {
        public function __construct(
            protected PaymentGateway $payment,
        ) {}

        public function store(Request $request)
        {
            $this->payment->charge(
                $request->amount,
                $request->payment_token
            );

            // ...
        }
    }
    ```
  </Step>
</Steps>

Mit diesem Muster genügt es, das Binding an einer einzigen Stelle zu ändern, wenn Sie den Zahlungsdienst zum Beispiel von `Stripe` auf einen anderen Anbieter umstellen möchten.

## Nächste Schritte

<Card title="Service-Provider" icon="plug" href="/de/service-providers">
  Erfahren Sie, wie Sie mit Service-Providern Bindings registrieren.
</Card>


## Related topics

- [Service-Provider](/de/service-providers.md)
- [Request-Lebenszyklus](/de/lifecycle.md)
- [Eigene Auth-Guards implementieren](/de/advanced/custom-auth-guard.md)
- [Anwendungsstruktur ab Laravel 11](/de/advanced/app-structure.md)
- [Laravel MCP](/de/mcp.md)
