Un package Laravel peut être comparé à une boîte à outils réutilisable pour vos projets. Il vous permet d'exploiter une fonctionnalité utile sur plusieurs projets sans avoir à la recoder systématiquement. Les packages offrent également la possibilité de partager vos créations avec la communauté Laravel.
Cet article détaillera la procédure de création d'un package Laravel, en abordant sa structuration, la rédaction de tests, et sa publication sur Packagist.
Pourquoi créer un package Laravel ?
Créer un package Laravel offre plusieurs avantages :
Réutilisabilité : Vous pouvez réutiliser le même code dans plusieurs projets sans avoir à le réécrire.
Modularité : Les packages permettent de diviser votre application en modules indépendants, ce qui facilite la maintenance et les mises à jour.
Partage : Vous pouvez partager vos packages avec la communauté Laravel, ce qui peut être bénéfique pour d'autres développeurs et pour votre propre réputation.
Organisation : Les packages aident à organiser votre code de manière plus structurée et logique.
Étapes pour Créer un Package Laravel
Étape 1 : Créer le dossier de votre package
il existe deux façon de commencer la création de votre package :
Créer dans un projet Laravel existant un dossier package à la racine
mkdir packages/my-name/package-nameCréer un dossier où vous voulez en dehors d’un projet Laravel
mkdir package-name
Ensuite, il suffit de se rendre dans le dossier précédemment créer et l'initialiser en tant que dépôt Git : git init
Étape 2 : Initialisation de composer
La création d’un package nécessite d’avoir un composer.json. Ce fichier indiquera à Packagist ce qu'est ce paquet et ce qu'il doit exécuter.
Deux possibilités :
Le faire à la main
En ligne de commande :
composer init
Comme nous construisons un package Laravel, la première chose dont nous aurons besoin est le package de support Laravel.
Il peut être installer via la commande : composer require illuminate/support
Le fichier doit ressembler à ceci :
{
"name": "my-name/package-name",
"description": "Description de mon package Laravel",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Votre Nom",
"email": "votre.email@example.com"
}
],
"require": {
"php": "^8.3",
"illuminate/support": "^11.0"
},
"require-dev": {},
"autoload": {
"psr-4": {
"MyName\\PackageName\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"MyName\\PackageName\\Tests\\": "tests/"
}
},
"extra": {
"laravel": {
"providers": [
"MyName\\PackageName\\Providers\\MonPackageServiceProvider"
]
}
},
"minimum-stability": "dev",
"prefer-stable": true
}Étape 3 : Création de notre fournisseur de services (Service Provider)
Ce fournisseur est le cœur de votre package, car il indique à Laravel comment charger le package et ce qui est disponible, telles que les vues, la configuration et les fichiers de localisation. Laravel détecte automatiquement les fournisseurs de services dans le dossier src. Pour ce faire, il faut créer la classe src/MonPackageServiceProvider.php.
Ce fichier contient deux méthodes :
register(): Enregistrer les services du packageboot(): Configuration et initialisation de tous les services du package
Les packages doivent souvent publier des ressources telles que des fichiers de configuration, des vues et des migrations vers l'application principale. Lorsque la commande Laravel vendor:publish sera lancée, les fichiers seront copié à l'emplacement spécifié.
<?php
declare(strict_types=1);
namespace MyName\PackageName\Providers;
use Illuminate\Support\ServiceProvider;
use MonVendor\MonPackage\Commands\MonCommande;
class MonPackageServiceProvider extends ServiceProvider
{
public function boot(): void
{
// Publication des fichiers de configuration
$this->publishes([
__DIR__.'/../../config/mon-package.php' => config_path('mon-package.php'),
], 'config');
// Publication des vues
$this->publishes([
__DIR__.'/../../resources/views' => resource_path('views/vendor/mon-package'),
], 'views');
// Publication des migrations
$this->publishes([
__DIR__.'/../../database/migrations' => database_path('migrations'),
], 'migrations');
// Chargement des vues
$this->loadViewsFrom(__DIR__.'/../../resources/views', 'mon-package');
// Chargement des migrations
$this->loadMigrationsFrom(__DIR__.'/../../database/migrations');
// Chargement des routes
$this->loadRoutesFrom(__DIR__.'/../../routes/web.php');
// Chargement des traductions
$this->loadTranslationsFrom(__DIR__.'/../../resources/lang', 'mon-package');
// Enregistrement des commandes Artisan
if ($this->app->runningInConsole()) {
$this->commands([
MaCommande::class,
]);
}
}
public function register(): void
{
// Fusion de la configuration
$this->mergeConfigFrom(
__DIR__.'/../../config/mon-package.php',
'mon-package'
);
// Enregistrement des services dans le conteneur
$this->app->singleton('mon-package', function ($app) {
return new \MyName\PackageName\MonPackage();
});
}
}Étape 4 : La configuration du Package
Créez un fichier de configuration dans le dossier src/config/mon-package.php :
<?php
return [
/*
|--------------------------------------------------------------------------
| Configuration de mon package
|--------------------------------------------------------------------------
|
| Ici vous pouvez définir toutes les options de configuration
| pour votre package.
|
*/
'key' => 'value',
];Étape 5 : Création des Vues
Créez des vues pour votre package dans resources/views/welcome.blade.php :
@extends('packageName::layouts.app')
@section('title', 'Bienvenue dans Mon Package' )
@section('content')
<section class="section">
<div class="container">
<p>{{ $message ?? "Message par défaut" }}</p>
</div>
</section>
@endsectionÉtape 6 : Création des routes et contrôleurs
Créez le fichier de routes routes/web.php :
<?php
use Illuminate\Support\Facades\Route;
use MyName\PackageName\Controllers\MonPackageController;
Route::prefix('package-name')
->name('packageName.')
->middleware('web')
->group(function () {
Route::get('/', [MonPackageController::class, 'index'])->name('index');
});Le contrôleur correspondant src/Controllers/MonPackageController.php :
<?php
declare(strict_types=1);
namespace MyName\PackageName\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\View\View;
class MonPackageController extends Controller
{
public function index(): View
{
return view('packageName::welcome', [
'message' => 'Votre package fonctionne parfaitement !'
]);
}
}Étape 7 : Les tests
C'est une étape très importante. Pour initialiser une suite de tests au sein de notre package, la méthode la plus simple consiste à utiliser pestPHP et Testbench.
composer require pestphp/pest --dev --with-all-dependencies
composer require --dev orchestra/testbenchAprès l'installation de pestPHP, il faut exécutez la commande : ./vendor/bin/pest --init
Cela générera le fichier phpunit.xml et un fichier tests/Pest.php permettant de contrôler et d'étendre Pest.
Pour les tests du package, il va falloir créer un fichier tests/PackageTestCase.php afin de pouvoir contrôler nos tests plus facilement et de pouvoir enregistrer notre fournisseur de services pour garantir son chargement dans l'application de test.
declare(strict_types=1);
namespace MyName\PackageName\Tests;
use MyName\PackageName\PackageServiceProvider;
use Orchestra\Testbench\TestCase;
class PackageTestCase extends TestCase
{
protected function getPackageProviders($app): array
{
return [
PackageServiceProvider::class,
];
}
}Il est important de ne pas oublier de modifier le fichier tests/Pest.php pour utiliser notre fichier PackageTestCase dans nos tests :
declare(strict_types=1);
use MyName\PackageName\Tests\PackageTestCase;
uses(PackageTestCase::class)->in(__DIR__);Pour la rédaction des tests, je vous invite à directement aller voir la documentation de pest : https://pestphp.com/docs/writing-tests
Étape 8 : La qualité de code
Chez Web^ID la qualité de code est également une étape très importante.
Nous allons commencer avec le style de code avec Laravel Pint : composer require --dev laravel/pint
Pint ne nécessite aucune configuration. Cependant, si vous souhaitez personnaliser les préréglages, les règles ou les dossiers inspectés, vous pouvez le faire en créant un fichier pint.json :
{
"preset": "laravel"
}En exécutant la commande pint ./vendor/bin/pint cela va corriger tous les problèmes de style de code qui ne sont pas conformes. Si vous le souhaitez Pint peut s'exécuter en mode parallèle : ./vendor/bin/pint --parallel .
Après Pint, nous avons Larastan qui est un outil d'analyse statique et permet de trouver des bugs dans votre application Laravel avant même qu'elle ne soit exécutée.
composer require --dev larastan/larastanPour configurer Larastan, il faut créer un fichier phpstan.neon.dist :
parameters:
level: max
paths:
- config
- database
- resources
- routes
- src
tmpDir: build/phpstanPour lancer l'analyse du code avec Larastan, il suffit d'utiliser la commande : php artisan code:analyse
Étape 9 : Documentation
Documenter correctement son package est essentiel :
Expliquer votre package
Donner les éléments requis pour l'utilisation du package
Donner la marche à suivre pour l'installation
....
Étape 10 : Installation
Pour utiliser votre package en local dans un projet Laravel, vous avez plusieurs possibilité, je vais vous en donner deux :
Votre package se trouve déjà dans votre projet Laravel, il faut ajouter dans le
composer.jsonde votre projet :
"repositories": [
{
"type": "path",
"url": "./packages/my-name/package-name"
}
],
"require": {
"my-name/package-name": "*"
}Votre package se trouve dans un autre dossier que votre projet Laravel.
Il vous suffit de faire un lien symbolique dans votre projet Laravel :
ln -s /chemin/vers/mon-package /chemin/vers/votre/projet/laravel/vendor/mon-vendeur/mon-packageEt de changer le
composer.jsoncomme haut dessus.
A la fin, votre package devrait avoir la structure suivante :
package-name/
├── src/
│ ├── Commands/
│ ├── Controllers/
│ ├── Models/
│ ├── Middleware/
│ ├── MonPackageServiceProvider.php
│ └── MonPackage.php
├── config/
│ └── mon-package.php
├── database/
│ ├── migrations/
│ └── seeders/
├── resources/
│ ├── views/
│ └── lang/
├── routes/
│ ├── web.php
│ └── api.php
├── tests/
├── vendor/
├── workbench/
├── .gitignore
├── composer.json
├── phpstan.neon.dist
├── pint.json
└── README.mdPublier votre package sur Packagist
Préparation
Si cela n'a pas été fait au début, initialiser votre dossier de package en tant que dépôt Git :
git initAjoutez tous vos fichiers et committez
(Optionnel) Créez des tags de version :
git tag v1.0.0
git push origin v1.0.0Utilisez le versioning sémantique (MAJOR.MINOR.PATCH) :
MAJOR : changements incompatibles
MINOR : nouvelles fonctionnalités compatibles
PATCH : corrections de bugs
Publication
Allez sur Packagist.org
Connectez-vous avec votre compte GitHub
Soumettez l'URL de votre repository
Packagist synchronisera automatiquement les nouvelles versions si vous avez ajouter des tags
Conclusion
La création d'un package Laravel demande une planification soignée mais offre de nombreux avantages : réutilisabilité, maintenabilité et possibilité de contribuer à la communauté.
Pour vous aider dans cette démarche, il est conseillé d'explorer les packages Laravel déjà disponibles sur Packagist. Cela vous permettra de vous familiariser avec les bonnes pratiques et les modèles fréquemment utilisés au sein de l'écosystème Laravel.