> ## 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

> Il meccanismo di dependency injection tramite il service container di Laravel e le basi del binding.

## Cos'è il service container

Il service container di Laravel è il meccanismo con cui vengono gestite le dipendenze delle classi e viene effettuata la dependency injection. Per dependency injection si intende "iniettare" nella classe le dipendenze di cui ha bisogno, tramite il costruttore o, in alcuni casi, tramite metodi setter.

Osserva l'esempio seguente.

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

namespace App\Http\Controllers;

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

class PodcastController extends Controller
{
    /**
     * Crea una nuova istanza del controller
     */
    public function __construct(
        protected AppleMusic $apple,
    ) {}

    /**
     * Mostra le informazioni del podcast indicato
     */
    public function show(string $id): View
    {
        return view('podcasts.show', [
            'podcast' => $this->apple->findPodcast($id)
        ]);
    }
}
```

In questo esempio, `PodcastController` deve recuperare un Podcast da una fonte dati come Apple Music. Per farlo **inietta** un servizio in grado di ottenerlo. Iniettando il servizio, nei test puoi sostituire facilmente `AppleMusic` con un mock (implementazione fittizia).

<Info>
  Comprendere a fondo il service container è essenziale per costruire applicazioni Laravel di grandi dimensioni. Torna utile anche per contribuire al core di Laravel.
</Info>

```mermaid theme={null}
flowchart TD
    A["Service provider<br>register()"] --> B["Service container<br>Registrazione dei binding"]
    B --> C{"Richiesta di risoluzione<br>make() / iniezione automatica"}
    C -- "Classe concreta" --> D["Risoluzione automatica<br>tramite reflection"]
    C -- "Interfaccia" --> E["Risolve l'implementazione<br>registrata"]
    D --> F["Crea l'istanza<br>e inietta nel costruttore"]
    E --> F
```

## Risoluzione zero-configuration

Se una classe dipende solo da altre classi concrete (non da interfacce), non devi indicare al container come risolverle. Ad esempio, supponi di scrivere questo codice in `routes/web.php`.

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

class Service
{
    // ...
}

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

<Info>
  In questo esempio la classe è definita nel file di route, ma è a scopo dimostrativo. Nelle applicazioni reali definisci le classi di servizio nella directory `app/Services`.
</Info>

Quando accedi alla route, Laravel risolve automaticamente la classe `Service` e la inietta nell'handler della route. Ottieni i benefici della dependency injection senza dover preparare file di configurazione.

Molte delle classi che scrivi in un'applicazione Laravel — controller, event listener, middleware, ecc. — ricevono automaticamente le dipendenze iniettate tramite il container.

## Binding

### Binding di base

La maggior parte dei binding si registra all'interno dei [service provider](/it/service-providers). Nei service provider puoi accedere al container tramite `$this->app`.

#### bind

Con il metodo `bind` registri un binding passando il nome della classe o dell'interfaccia e una closure.

```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));
});
```

Come argomento della closure ricevi il container stesso, che puoi usare per risolvere sotto-dipendenze.

Per interagire con il container al di fuori dei service provider usa la facade `App`.

```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>
  Non è necessario fare il binding delle classi che non dipendono da interfacce. Il container le risolve automaticamente tramite reflection.
</Info>

#### singleton

Il metodo `singleton` esegue il binding facendo in modo che la classe o l'interfaccia venga risolta una sola volta. Ogni chiamata successiva al container restituirà la stessa istanza.

```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

Puoi anche fare il binding di un'istanza già esistente con il metodo `instance`. Ogni chiamata successiva restituirà quella stessa istanza.

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

$service = new Transistor(new PodcastParser);

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

### Binding di un'interfaccia a un'implementazione

Una funzionalità potente del service container è la possibilità di legare un'interfaccia a un'implementazione specifica. Ad esempio, supponi di avere l'interfaccia `EventPusher` e l'implementazione `RedisEventPusher`.

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

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

In questo modo il container inietta `RedisEventPusher` nelle classi che richiedono un'implementazione di `EventPusher`. Ti basta fare il type hint di `EventPusher` nel costruttore.

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

/**
 * Crea una nuova istanza della classe
 */
public function __construct(
    protected EventPusher $pusher,
) {}
```

<Tip>
  Dipendendo dall'interfaccia, cambiare implementazione non richiede modifiche al codice. Facilita test e cambiamenti futuri.
</Tip>

## Risoluzione automatica (DI tramite type hint)

Quando il service container risolve classi come controller, event listener e middleware, guarda il type hint del costruttore e inietta automaticamente le dipendenze.

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

namespace App\Http\Controllers;

use App\Repositories\UserRepository;

class UserController extends Controller
{
    /**
     * Crea una nuova istanza del controller
     */
    public function __construct(
        protected UserRepository $users,
    ) {}
}
```

Se `UserRepository` non dipende da un'interfaccia, non è necessario registrarlo nel container. Basta accedere alla route e il container risolverà e inietterà automaticamente la dipendenza nel controller.

## Risoluzione dal container

### Metodo make

Con il metodo `make` puoi risolvere un'istanza di classe dal container.

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

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

Se una dipendenza non può essere risolta dal container, puoi passare argomenti aggiuntivi con `makeWith`.

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

### Iniezione automatica

In pratica raramente chiamerai direttamente `make`. Aggiungi il type hint nel costruttore delle classi che il container risolve (controller, event listener, middleware, ecc.) e il container si occuperà dell'iniezione.

## Relazione tra facade e container

Le facade di Laravel forniscono un'interfaccia statica agli oggetti presenti nel container. Ad esempio, `Cache::get()` internamente ottiene il servizio `Cache` dal container e lo chiama.

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

// Chiamata tramite facade
Cache::get('key');

// Chiamata equivalente diretta al container
app('cache')->get('key');
```

Le facade sono comodi wrapper del container. Nei test puoi sostituirle con mock.

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

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

## Esempio pratico di constructor injection

Ecco un pattern tipico in un'applicazione reale.

<Steps>
  <Step title="Definisci l'interfaccia">
    ```php theme={null}
    <?php

    namespace App\Contracts;

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

  <Step title="Crea la classe di implementazione">
    ```php theme={null}
    <?php

    namespace App\Services;

    use App\Contracts\PaymentGateway;

    class StripePaymentGateway implements PaymentGateway
    {
        public function charge(int $amount, string $token): bool
        {
            // Logica di pagamento tramite l'API Stripe...
            return true;
        }
    }
    ```
  </Step>

  <Step title="Effettua il binding in un service provider">
    ```php theme={null}
    use App\Contracts\PaymentGateway;
    use App\Services\StripePaymentGateway;

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

  <Step title="Ricevi l'iniezione nel controller">
    ```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>

Con questo pattern, per passare da `Stripe` a un altro provider basta modificare il binding in un unico punto.

## Prossimi passi

<Card title="Service provider" icon="plug" href="/it/service-providers">
  Impara come registrare i binding usando i service provider.
</Card>


## Related topics

- [Service provider](/it/service-providers.md)
- [Ciclo di vita della richiesta](/it/lifecycle.md)
- [Implementare un guard di autenticazione personalizzato](/it/advanced/custom-auth-guard.md)
- [Struttura dell'applicazione da Laravel 11](/it/advanced/app-structure.md)
- [Mock](/it/mocking.md)
