I service providers di laravel sono il luogo centrale in cui l’applicazione viene avviata. Cioè, i servizi principali di laravel e i servizi, le classi e le relative dipendenze dell’applicazione vengono inseriti nel contenitore di servizi tramite i provider. 

In altre parole, i service providers sono come un imbuto attraverso il quale versiamo carburante “classi” in un serbatoio chiamato “contenitore di servizio” di un motore chiamato Laravel.

Tempo di lettura stimato: 5 minuti

Esempio

Se apriamo config/app.php vedremo un array con il nome “provider”

'providers' => [

        /*
        * Laravel Framework Service Providers...
        */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        Illuminate\Cookie\CookieServiceProvider::class,
        .
        .
        .
],

Questi sono alcuni dei service providers forniti insieme a laravel, cioè servizi di base che vengono inseriti nel contenitore di servizi.

Quando i service provider vengono eseguiti ?

Se guardiamo la documentazione su request lifecycle , i seguenti file vengono eseguiti all’inizio:

  • public/index.php
  • bootstrap/app.php
  • app/Http/Kernel.php e i suoi Middlewares
  • Service Providers: contenuto di questo articolo

Quali service provider vengono caricati ? 

Sono quelli definiti nell’array config/app.php:

return [
 
    // ... other configuration values
 
    'providers' => [
 
        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
 
        // ... other framework providers from /vendor
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,
 
        /*
         * PUBLIC Service Providers - the ones we mentioned above
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
 
    ],
 
];

Come possiamo vedere, c’è un elenco di service provider non pubblici nella cartella /vendor, non dovremmo nè toccarli e nè modificarli. Quelli che ci interessano sono in basso, con BroadcastServicerProvider disabilitato di default, probabilmente perché usato raramente.

Tutti questi fornitori di servizi vengono eseguiti dall’alto verso il basso, ripetendo l’elenco due volte:

  • La prima iterazione è alla ricerca di un metodo facoltativo register(), utile per eseguire (eventualmente) qualcosa di configurato prima del metodo boot().
  • la seconda iterazione esegue il metodo boot() di tutti i provider. Di nuovo, uno per uno, dall’alto verso il basso, dell’array 'providers'.
  • Infine, dopo che tutti i fornitori di servizi sono stati elaborati, Laravel passa all’analisi del percorso (della rotta), all’esecuzione del controller, all’utilizzo dei modelli, ecc.

Service Providers Laravel predefiniti

I Service Providers inclusi in Laravel, sono tutti quelli presenti nella cartella app/Providers:

  • AppServiceProvider
  • AuthServiceProvider
  • BroadcastServiceProvider
  • EventServiceProvider
  • RouteServiceProvider

Sono tutte classi PHP, ciascuna correlata al proprio argomento: App, Auth, Broadcasting, Events e Routes. Ma hanno tutti una cosa in comune: il metodo boot().

All’interno di quel metodo, possiamo scrivere qualsiasi codice relativo a una di quelle sezioni: auth, events, route, ecc. In altre parole, i Service Provider sono solo classi per registrare alcune funzionalità globali.

Sono separati come “provider” perché vengono eseguiti molto presto nel ciclo di vita dell’applicazione, quindi è conveniente qualcosa di globale qui prima che lo script di esecuzione arrivi a Models o Controllers.

La maggior quantità di funzionalità è nel RouteServiceProvider, ecco qui il codice:

class RouteServiceProvider extends ServiceProvider
{
    public const HOME = '/dashboard';
 
    public function boot()
    {
        $this->configureRateLimiting();
 
        $this->routes(function () {
            Route::prefix('api')
                ->middleware('api')
                ->group(base_path('routes/api.php'));
 
            Route::middleware('web')
                ->group(base_path('routes/web.php'));
        });
    }
 
    protected function configureRateLimiting()
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });
    }
}

Questa è la classe in cui sono configurati i file di route, con routes/web.phproutes/api.php inclusi per impostazione predefinita. Si noti che per l’API ci sono anche diverse configurazioni: prefisso dell’endpoint /api e middleware api per tutti i routes.

Possiamo modificare i service providers, che non sono nella cartella /vendor. La personalizzazione di questi file si effettua quando si hanno molti percorsi e si desidera separarli in file specifici. Crei routes/auth.php e metti lì i percorsi, quindi “abiliti” quel file nel metodo boot() di RouteServiceProvider, aggiungi solo la terza frase:

Articoli correlati
Newsletter sull’Innovazione
Non perderti le notizie più importanti sull'Innovazione. Iscriviti per riceverle via e-mail.
`Route::middleware('web') // or maybe you want another middleware?
    ->group(base_path('routes/auth.php'));

AppServiceProvider è vuoto. Un esempio tipico di aggiunta di codice AppServiceProvider, riguarda la disabilitazione del caricamento lento in Eloquent . Per fare ciò, devi solo aggiungere due righe nel metodo boot():

// app/Providers/AppServiceProvider.php
use Illuminate\Database\Eloquent\Model;
 
public function boot()
{
    Model::preventLazyLoading(! $this->app->isProduction());
}

Ciò genererà un’eccezione se un modello di relazione non è caricato.

Crea il tuo service provider personalizzato

Oltre ai file predefiniti esistenti, possiamo facilmente creare un nuovo Service Provider, relativo ad altri argomenti rispetto a quelli predefiniti come auth/event/routes.

Un esempio abbastanza tipico è la configurazione relativa alle viste Blade. Possiamo creare una direttiva Blade, e poi aggiungere quel codice nel metodo boot() di qualsiasi service provider, incluso il default AppServiceProvider. Creiamo ora un ViewServiceProvider separato.

Possiamo generarlo con questo comando:

php artisan make:provider ViewServiceProvider

Che genererà la classe in modo predefinito:

namespace App\Providers;
 
use Illuminate\Support\ServiceProvider;
 
class ViewServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
 
    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

Come possiamo vedere all’interno ci sono due metodi:

Il metodo register()

Il metodo register() ci consente di definire i collegamenti al nostro contenitore di servizi. Ad esempio, nel codice seguente:

public function register()
{
    $this->app->singleton(my_class, function($app){
        return new MyClass($app);
    });
}

$this->app è una variabile globale in laravel che può accedere a una classe singleton tramite l’app.

Singleton è una caratteristica. Quando si applica questa caratteristica, stiamo informando l’applicazione che qualunque classe venga inviata come parametro nell’app dovrebbe avere una sola istanza in tutta l’applicazione. Ciò significa che MyClass verrà risolto una volta e avrà solo un’istanza, a cui è possibile accedere utilizzando la variabile my_class.

Il metodo boot()

Il metodo boot() consente di accedere a tutti i servizi precedentemente registrati utilizzando il metodo register. È quindi possibile includere l’intero servizio nella propria applicazione utilizzando questo metodo.

Tornando all’esempio precedente, rimuoviamo il metodo register() e all’interno di boot() aggiungere il codice della direttiva Blade:

use Illuminate\Support\Facades\Blade;
 
public function boot()
{
    Blade::directive('datetime', function ($expression) {
        return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
    });
}

Un altro esempio di ViewServiceProvider riguarda View Composers, ecco lo snippet dal sito ufficiale di Laravel :

use App\View\Composers\ProfileComposer;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
 
class ViewServiceProvider extends ServiceProvider
{
    public function boot()
    {
        // Using class based composers...
        View::composer('profile', ProfileComposer::class);
 
        // Using closure based composers...
        View::composer('dashboard', function ($view) {
            //
        });
    }
}

Per essere eseguito, questo nuovo provider deve essere aggiunto/registrato all’array di provider in config/app.php:

return [
    // ... other configuration values
 
    'providers' => [
 
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
 
        // Add your provider here
        App\Providers\ViewServiceProvider::class,
    ],
];

Ercole Palmeri

Potrebbero interessarti anche:

Newsletter sull’Innovazione
Non perderti le notizie più importanti sull'Innovazione. Iscriviti per riceverle via e-mail.