Fournisseurs de services à Laravel : qu’est-ce qu’ils sont et comment les utiliser

Pour ceux qui n’ont pas activement utilisé les fournisseurs de services dans Laravel, c’est un “terme” mystique : quel “service” “fournissent-ils” réellement, et comment tout cela fonctionne-t-il exactement ? Je vais l’expliquer dans cet article.


Fournisseurs de services Laravel par défaut

Commençons par les fournisseurs de services par défaut inclus dans Laravel, ils sont tous dans le app/Providers dossier:

  • AppServiceProvider
  • AuthServiceProviderAuthServiceProvider
  • BroadcastServiceProvider
  • EventServiceProvider
  • RouteServiceProviderRouteServiceProvider

Ce sont toutes des classes PHP, chacune liée à son sujet : “application” générale, Auth, Diffusion, Événements et Routes. Mais ils ont tous un point commun : le boot() méthode.

À l’intérieur de cette méthode, vous pouvez écrire n’importe quel code lié à l’une de ces sections : auth, événements, itinéraires, etc. En d’autres termes, les fournisseurs de services ne sont que des classes pour enregistrer certaines fonctionnalités globales.

Ils sont séparés en tant que “fournisseurs” car ils sont exécutés très tôt dans le cycle de vie de l’application, il est donc pratique pour quelque chose de global ici avant que le script d’exécution n’arrive aux modèles ou aux contrôleurs.

La plupart des fonctionnalités se trouvent dans le RouteServiceProvider, jetons un coup d’œil à son code :

1class RouteServiceProvider extends ServiceProvider

2{

3 public const HOME = '/dashboard';

4 

5 public function boot()

6 {

7 $this->configureRateLimiting();

8 

9 $this->routes(function () {

10 Route::prefix('api')

11 ->middleware('api')

12 ->group(base_path('routes/api.php'));

13 

14 Route::middleware('web')

15 ->group(base_path('routes/web.php'));

16 });

17 }

18 

19 protected function configureRateLimiting()

20 {

21 RateLimiter::for('api', function (Request $request) {

22 return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());

23 });

24 }

25}

C’est la classe où les fichiers de route sont configurés, avec routes/web.php et routes/api.php inclus par défaut. Notez que pour l’API, il existe également différentes configurations : préfixe de point de terminaison /api et middleware api pour tous les parcours.

Vous pouvez modifier ces fournisseurs de services comme vous le souhaitez, ils ne sont pas dans le /vendor dossier. La personnalisation typique de ce fichier se produit lorsque vous avez beaucoup d’itinéraires et que vous souhaitez les séparer dans votre fichier personnalisé. Tu crées routes/auth.php et y mettre les routes, puis vous “activez” ce fichier dans le boot() méthode de la RouteServiceProviderajoutez simplement la troisième phrase :

1`Route::middleware('web') // or maybe you want another middleware?

2 ->group(base_path('routes/auth.php'));

D’autres fournisseurs de services par défaut ont d’autres fonctionnalités, vous pouvez les analyser vous-même. À l’exception de AppServiceProvideril est vide, comme un espace réservé pour nous permettre d’ajouter tout code lié à certains paramètres d’application globaux.

Un exemple populaire d’ajout de code au AppServiceProvider consiste à désactiver le chargement paresseux dans Eloquent. Pour ce faire, il vous suffit d’ajouter deux lignes dans le boot() méthode:

1// app/Providers/AppServiceProvider.php

2use IlluminateDatabaseEloquentModel;

3 

4public function boot()

5{

6 Model::preventLazyLoading(! $this->app->isProduction());

7}

Cela lèvera une exception si un modèle de relation n’est pas chargé avec impatience, ce qui provoque un problème de requête dit N + 1 avec les performances.


Quand les fournisseurs de services sont-ils exécutés ?

Si vous regardez les documents officiels sur la demande de cycle de vie, voici les choses exécutées au tout début :

  • public/index.php
  • bootstrap/app.php
  • app/Http/Kernel.php et ses middlewares
  • Fournisseurs de services : exactement notre sujet de cet article

Quels fournisseurs sont chargés ? Il est défini dans le config/app.php déployer:

1return [

2 

3 // ... other configuration values

4 

5 'providers' => [

6 

7 /*

8 * Laravel Framework Service Providers...

9 */

10 IlluminateAuthAuthServiceProvider::class,

11 IlluminateBroadcastingBroadcastServiceProvider::class,

12 

13 // ... other framework providers from /vendor

14 IlluminateValidationValidationServiceProvider::class,

15 IlluminateViewViewServiceProvider::class,

16 

17 /*

18 * PUBLIC Service Providers - the ones we mentioned above

19 */

20 AppProvidersAppServiceProvider::class,

21 AppProvidersAuthServiceProvider::class,

22 // AppProvidersBroadcastServiceProvider::class,

23 AppProvidersEventServiceProvider::class,

24 AppProvidersRouteServiceProvider::class,

25 

26 ],

27 

28];

Comme vous pouvez le constater, il existe une liste de fournisseurs de services non publics du /vendor dossier, vous ne devriez pas les toucher/modifier. Ceux qui nous intéressent sont en bas, avec BroadcastServicerProvider désactivé par défaut, probablement parce qu’il est rarement utilisé.

Tous ces fournisseurs de services sont exécutés de haut en bas, en itérant cette liste deux fois.

La première itération recherche une méthode optionnelle register() qui peut être utilisé pour initier quelque chose avant le boot() méthode. Je ne l’ai jamais utilisé dans mon expérience.

Ensuite, la deuxième itération exécute le boot() méthode de tous les fournisseurs. Encore une fois, un par un, de haut en bas du 'providers' déployer.

Et puis, une fois que tous les fournisseurs de services ont été traités, Laravel analyse la route, exécute le contrôleur, utilise des modèles, etc.


Créez votre fournisseur de services personnalisé

En plus des fichiers par défaut existants, vous pouvez facilement créer votre fournisseur de services, lié à d’autres sujets que ceux par défaut comme auth/event/routes.

Un exemple assez typique est la configuration liée aux vues Blade. Si vous souhaitez créer votre directive Blade, vous pouvez ajouter ce code dans n’importe quel fournisseur de services. boot() méthode, y compris la valeur par défaut AppServiceProvidermais assez souvent, les développeurs créent un ViewServiceProvider distinct.

Vous pouvez le générer avec cette commande :

1php artisan make:provider ViewServiceProvider

Il générera le modèle par défaut :

1namespace AppProviders;

2 

3use IlluminateSupportServiceProvider;

4 

5class ViewServiceProvider extends ServiceProvider

6{

7 /**

8 * Register services.

9 *

10 * @return void

11 */

12 public function register()

13 {

14 //

15 }

16 

17 /**

18 * Bootstrap services.

19 *

20 * @return void

21 */

22 public function boot()

23 {

24 //

25 }

26}

Vous pouvez retirer le register() méthode, et à l’intérieur de boot() ajoutez le code de la directive Blade :

1use IlluminateSupportFacadesBlade;

2 

3public function boot()

4{

5 Blade::directive('datetime', function ($expression) {

6 return "echo ($expression)->format('m/d/Y H:i'); ?>";

7 });

8}

Un autre exemple de ViewServiceProvider concerne les View Composers, voici l’extrait de la documentation officielle de Laravel :

1use AppViewComposersProfileComposer;

2use IlluminateSupportFacadesView;

3use IlluminateSupportServiceProvider;

4 

5class ViewServiceProvider extends ServiceProvider

6{

7 public function boot()

8 {

9 // Using class based composers...

10 View::composer('profile', ProfileComposer::class);

11 

12 // Using closure based composers...

13 View::composer('dashboard', function ($view) {

14 //

15 });

16 }

17}

Pour être exécuté, ce nouveau fournisseur doit être ajouté au tableau des fournisseurs dans config/app.phpcomme mentionné ci-dessus:

1return [

2 // ... other configuration values

3 

4 'providers' => [

5 

6 AppProvidersAppServiceProvider::class,

7 AppProvidersAuthServiceProvider::class,

8 // AppProvidersBroadcastServiceProvider::class,

9 AppProvidersEventServiceProvider::class,

10 AppProvidersRouteServiceProvider::class,

11 

12 // Add your provider here

13 AppProvidersViewServiceProvider::class,

14 ],

15];


Exemples de projets Open Source

Enfin, je souhaite mentionner quelques exemples de projets Laravel disponibles gratuitement.

1. spatie/freek.dev : BladeComponentServiceProvider

Une société bien connue, Spatie, a publié le code source du blog personnel de Freek van der Hertenavec ce fichier.

app/Providers/BladeComponentServiceProvider.php:

1namespace AppProviders;

2 

3use AppHttpComponentsAdComponent;

4use IlluminateSupportFacadesBlade;

5use IlluminateSupportServiceProvider;

6 

7class BladeComponentServiceProvider extends ServiceProvider

8{

9 public function boot()

10 {

11 Blade::component('ad', AdComponent::class);

12 

13 Blade::component('front.components.inputField', 'input-field');

14 Blade::component('front.components.submitButton', 'submit-button');

15 Blade::component('front.components.textarea', 'textarea');

16 Blade::component('front.components.textarea', 'textarea');

17 Blade::component('front.components.shareButton', 'share-button');

18 Blade::component('front.components.lazy', 'lazy');

19 Blade::component('front.components.postHeader', 'post-header');

20 

21 Blade::component('front.layouts.app', 'app-layout');

22 }

23}

Voir la source sur Github

2. monicahq/monica : MacroServiceProvider

L’un des projets open source Laravel les plus appréciés a un fichier séparé pour enregistrer les macros Collection :

app/Providers/MacroServiceProvider.php:

1namespace AppProviders;

2 

3use AppHelpersCollectionHelper;

4use IlluminateSupportCollection;

5use IlluminateSupportServiceProvider;

6 

7class MacroServiceProvider extends ServiceProvider

8{

9 /**

10 * Bootstrap any application services.

11 *

12 * @return void

13 */

14 public function boot()

15 {

16 if (! Collection::hasMacro('sortByCollator')) {

17 Collection::macro('sortByCollator', function ($callback, $options = Collator::SORT_STRING, $descending = false) {

18 /** @var Collection */

19 $collect = $this;

20 

21 return CollectionHelper::sortByCollator($collect, $callback, $options, $descending);

22 });

23 }

24 

25 if (! Collection::hasMacro('groupByItemsProperty')) {

26 Collection::macro('groupByItemsProperty', function ($property) {

27 /** @var Collection */

28 $collect = $this;

29 

30 return CollectionHelper::groupByItemsProperty($collect, $property);

31 });

32 }

33 

34 if (! Collection::hasMacro('mapUuid')) {

35 Collection::macro('mapUuid', function () {

36 /** @var Collection */

37 $collect = $this;

38 

39 return $collect->map(function ($item) {

40 return $item->uuid;

41 })->toArray();

42 });

43 }

44 }

45}

Voir la source sur Github

3. phpreel/phpreelcms : fournisseur de services de composants de tableau de bord

Laravel CMS appelé phpReel dispose également d’un fournisseur de services pour les composants Blade, nommé encore plus longtemps.

app/Providers/DashboardComponentsServiceProvider.php:

1 

2namespace AppProviders;

3 

4use IlluminateSupportServiceProvider;

5use IlluminateSupportFacadesBlade;

6use AppHelpersFileUploadUploadComponents;

7 

8class DashboardComponentsServiceProvider extends ServiceProvider

9{

10 /**

11 * Register services.

12 *

13 * @return void

14 */

15 public function register()

16 {

17 //

18 }

19 

20 /**

21 * Bootstrap services.

22 *

23 * @return void

24 */

25 public function boot()

26 {

27 Blade::directive('uploadForm', function () {

28 $component = UploadComponents::getUploadForm();

29 $html = 'echo '' . $component . ''; ?>';

30 

31 return (' . $component . '"; ?>');

32 });

33 }

34}

Voir la source sur Github

Vous pouvez également trouver quelques exemples supplémentaires de fournisseurs de services sur mon site Web LaravelExamples.com.

Leave a Comment

Your email address will not be published. Required fields are marked *