Fabrice Planchette

Ecrire un package Laravel

Jul 1, 2020

DRY ! Oui tu as raison c’est un acronyme : Don’t Repeat Yourself - Ne te répète pas. L’idée d’un package est de contenir du code qui répond à un besoin précis et qui pourra être utiliser dans diverses applications.

Création d’un package Laravel

Un package Laravel démarre avec 2 fichiers :

  • un fichier composer.json qui renseignera la manière de charger tes classes (oui je parle de PSR-4 là)
  • une classe ServiceProvider qui sert à l’initialisation de ton package.

Composer.json

Voilà à quoi doit ressembler le fichier composer.json. Tu noteras que j’ai volontairement omis les tests unitaires dans le fichier. Oui c’est volontaire, j’espère sortir un article dédié sur le sujet bientôt ;)

{
    "name": "fabpl/package",
    "description": "My awesome package",
    "homepage": "https://github.com/fabpl/package",
    "license": "MIT",
    "type": "library",
    "authors": [
        {
            "name": "Fabrice PLANCHETTE",
            "role": "Developer"
        }
    ],
    "require": {
        "php": "^7.1",
        "illuminate/support": "^6.0"
    },
    "autoload": {
        "psr-4": {
            "Fabpl\\Package\\": "src"
        }
    },
    "config": {
        "sort-packages": true
    },
    "extra": {
        "laravel": {
            "providers": [
                "Fabpl\\Package\\PackageServiceProvider"
            ]
        }
    }
}

Service Provider

Laravel se charge tout seul de “découvrir” notre service provider (si si, c’est écrit dans la documentation), reste plus qu’à écrire son contenu :

<?php

namespace Fabpl\Package;

use Illuminate\Support\ServiceProvider;

class PackageServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     */
    public function register()
    {
        //
    }
}

Bah, t’as rien mis dans tes méthodes boot() et register ? C’est une blague ? Tu serais pas impatient toi ? Attends, je te détaille ça.

Déjà il faut comprendre la différence. Une fois que tous les services providers ait été enregistrés (registered), ils vont être “booter”.

Boot

Tu y mettras notamment ce qui doit être “charger”. Fichiers de traduction, de migrations, les vues et… les routes.

Je te donne quelques exemples :

$this->loadTranslationsFrom(__DIR__.'/../resources/lang', 'package');
$this->loadViewsFrom(__DIR__.'/../resources/views', 'package');
$this->loadMigrationsFrom(__DIR__.'/../database/migrations');
$this->loadRoutesFrom(__DIR__.'/routes.php');

Tu vas également renseigner ce qui peut être “publier”, c’est à dire copier vers l’application.

if ($this->app->runningInConsole()) {
    $this->publishes([
        __DIR__.'/../config/config.php' => config_path('package.php'),
    ], 'config');
    
    // Publishing the views.
    $this->publishes([
        __DIR__.'/../resources/views' => resource_path('views/vendor/package'),
    ], 'views');
    
    // Publishing assets.
    $this->publishes([
        __DIR__.'/../resources/assets' => public_path('vendor/package'),
    ], 'assets');
    
    // Publishing the translation files.
    $this->publishes([
        __DIR__.'/../resources/lang' => resource_path('lang/vendor/package'),
    ], 'lang');
}

Et le dernier truc, c’est si tu as des commandes artisan à enregister :

if ($this->app->runningInConsole()) {
    $this->commands([
        FooCommand::class,
    ]);
}

Register

Le 1er truc à faire c’est de merger la config par défaut que tu as mis dans ton package, et celle que pourra surcharger le développement dans son application.

$this->mergeConfigFrom(__DIR__.'/../config/config.php', 'package');

C’est également dans cette méthode que tu vas enregistrer tes singletons.

Mais je t’en ai trop dit, faut aller voir la documentation sur Laravel maintenant.

Ah si j’oubliais ! Le top pour apprendre c’est de fouiller dans les packages des autres. y’a notamment Spatie qui en fait énormement de package pour Laravel.