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.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).
Comprendere a fondo il service container è essenziale per costruire applicazioni Laravel di grandi dimensioni. Torna utile anche per contribuire al core di Laravel.
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 inroutes/web.php.
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.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. Nei service provider puoi accedere al container tramite$this->app.
bind
Con il metodobind registri un binding passando il nome della classe o dell’interfaccia e una closure.
App.
Non è necessario fare il binding delle classi che non dipendono da interfacce. Il container le risolve automaticamente tramite reflection.
singleton
Il metodosingleton 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.
instance
Puoi anche fare il binding di un’istanza già esistente con il metodoinstance. Ogni chiamata successiva restituirà quella stessa istanza.
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’interfacciaEventPusher e l’implementazione RedisEventPusher.
RedisEventPusher nelle classi che richiedono un’implementazione di EventPusher. Ti basta fare il type hint di EventPusher nel costruttore.
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.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 metodomake puoi risolvere un’istanza di classe dal container.
makeWith.
Iniezione automatica
In pratica raramente chiamerai direttamentemake. 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.
Esempio pratico di constructor injection
Ecco un pattern tipico in un’applicazione reale.
Con questo pattern, per passare da
Stripe a un altro provider basta modificare il binding in un unico punto.
Prossimi passi
Service provider
Impara come registrare i binding usando i service provider.