I service provider rappresentano il cuore del framework, la parte interna che si occupa di registrare e avviare tutti i componenti presenti in una WebApp, come ad esempio i servizi, eventuali listener di eventi, i middleware e le rotte. All'interno del file config/app.php
è possibile visualizzare l'elenco dei service provider configurati per la nostra applicazione.
Ovviamente Laravel viene fornito con un set di service provider già configurati: alcuni di questi fanno parte del framework vero e proprio (quelli che appartengono al namespace Illuminate\
) mentre altri, nonostante sono già automaticamente disponibili, sono fisicamente locati all'interno del nostro progetto (in app/Providers
) e che appartengono al namespace custom definito (nel caso della nostra applicazione Biblios\
). Tale differenza risiede nel fatto che questi ultimi presentano funzionalità che potrebbero essere personalizzate e quindi gli autori del framework hanno deciso di rendere eventuali modifiche più semplici.
Nel dettaglio i service provider sono:
Service Provider | Descrizione |
---|---|
AppServiceProvider |
Un service provider vuoto, da utilizzare per piccole configurazioni. |
AuthServiceProvider |
Un service provider utilizzato per definire il modello di autenticazione scelto. |
EventServiceProvider |
Un service provider dedicato alla registrazione di eventuali eventi custom. |
RouteServiceProvider |
Un service dedicato alla configurazione delle rotte al cui interno viene incluso il classico app/Http/Routes.php . |
Creare service provider
Oltre ai service provider già disponibili in Laravel è ovviamente possibile registrarne altri. Il suggerimento è quello di crearne di nuovi solamente se i 4 descritti precedentemente non sono sufficienti. Per esempio per definire comportamenti personalizzati a livello di rotte o per creare eventi application-wide bisognerebbe utilizzare rispettivamente il RouteServiceProvider
e l'EventServiceProvider
.
Per creare nuovi provider Laravel mette a disposizione il comando
php artisan make:provider NomeProvider
I provider così creati verranno posizionati insieme agli altri in app/Providers
. Le classi create dovranno estendere Illuminate\Support\ServiceProvider
e dovranno avere due metodi: register
e boot
. Ovviamente generando il file con make:provider
tutto sarà già correttamente configurato.
Il metodo register
deve occuparsi esclusivamente della registrazione di nuovi componenti all'interno del service container. Non è consigliato scrivere frammenti di codice diversi dalla registrazione perché il metodo viene invocato prima del completamento del container e quindi eventuali servizi richiesti potrebbero non essere ancora pronti e istanziabili.
Il metodo boot
deve occuparsi di eventuali altre logiche da demandare al service provider, come per esempio configurare dei ViewComposer
. All'interno del metodo boot
, abbiamo la certezza che il service container è già stato inizializzato con successo e che quindi tutti i componenti sono già stati bindati con successo.
Una volta definita la nostra classe è necessario registrare il service provider appena definito all'interno del file config/app.php
nella sezione providers
.
Biblios, servizi e provider
Il nostro progetto è rimasto fermo da qualche articolo. La situazione attuale è la seguente:
- i modelli disponibili sono
Book
,Author
eUser
. TraBook
eAuthor
esiste una relazione uno a molti, mentre traBook
eUser
una relazione molti a molti (che permette di capire quali utenti hanno letto quali libri). - All'url
/book
è disponibile l'anagrafica dei libri, gestita dalBookController
. - All'url
/author
è disponibile l'anagrafica degli autori, gestita dall'AuthorController
. - Le rotte sono configurate tramite
Route::resource
La parte disponibile potrebbe essere considerata una sezione di BackOffice (anche se non ancora resa privata). Occupiamoci ora di definire la parte publica a partire dalla home. La homepage presenterà diverse sezioni:
- Gli ultimi 3 libri caricati in catalogo.
- I 3 autori più prolifici.
Questi blocchi di contenuti dovranno essere riutilizzati in differenti pagine del sito e per questo motivo creeremo dei ViewComposer
.
Partiamo quindi creando un ViewComposerServiceProvider
con il comando
php artisan make:provider ViewComposerServiceProvider
e lo registriamo in config/app.php
. Nel provider registriamo due view composer:
public function boot()
{
View::composer('shared.lastBook', \Biblios\Http\ViewComposers\LastBookViewComposer::class);
View::composer('shared.prolificAuthor', \Biblios\Http\ViewComposers\ProlificAuthorViewComposer::class);
}
Creiamo quindi i due view composer, il primo che si occuperà di recuperare gli ultimi 3 libri e il secondo i 3 autori più prolifici.
class LastBookViewComposer {
protected $lastBookList = [];
public function __construct() {
$this->lastBookList = Book::orderBy('created_at', 'desc')->limit(3)->get();
}
public function compose(View $view) {
$view->with('lastBookList', $this->lastBookList);
}
}
class ProlificAuthorViewComposer {
protected $prolificAuthorList = [];
public function __construct() {
$this->prolificAuthorList = Author::with('books')->limit(3)->get()->sortBy(function($author) {
return $author->books->count();
})->reverse();
}
public function compose(View $view) {
$view->with('prolificAuthorList', $this->prolificAuthorList);
}
}
Passiamo quindi alla creazione di una nuova rotta per la homepage nella quale includeremo due viste che dovranno chiamarsi esattamente come i nomi registrati nel service provider: shared.lastBook
e shared.prolificAuthor
. Puntiamo quindi il nostro browser su:
localhost:8000
e dovremmo vedere le due liste.