Le pattern Pipeline

Publié le 16 mai 2022 par Mathieu De Gracia
Couverture de l'article Le pattern Pipeline

Laravel dispose depuis sa version 5.0.30 d'un puissant service de Pipeline.

Il est pourtant grandement méconnu des développeurs Laravel de par son absence de la documentation officielle.

Explorons ensemble les possibilités que propose ce pattern !

Le cœur de Laravel est un pipeline

Toutes requêtes HTTP entrant dans votre Laravel passe par une série de middleware.

Ces middlewares peuvent être vus comme un empilement de class qu'une requête doit entièrement traverser avant d'atteindre vos controllers.

Ces class peuvent ainsi manipuler la requête en amont de votre application, en vérifiant par exemple la validité du token CSRF, en démarrant les sessions, l'authentification ...

Mais saviez que toute cette mécanique interne ... fonctionnait à l'aide d'un pipeline ?

Ces middlewares constituent cette "stack" d'étape, que l'on appelle communément Pipes, qu'une variable $request doit franchir sans encombre.

Dans le cas d'un Laravel 9, vous pouvez voir ce Pipeline en action dans la méthode sendRequestThroughRouter de la class Illuminate\Foundation\Http\Kernel.php !

Exemple d'utilisation

Le pattern Pipeline fonctionne en trois temps.

Tout d'abord, la variable que l'on veut manipuler doit être transmise au pipeline depuis la méthode send.

1use Illuminate\Pipeline\Pipeline;
2 
3app(Pipeline::class)
4 ->send($a = 0);

Dans un second temps, il est nécessaire de transmettre un array à la méthode through contenant la liste des pipes que notre variable devra traverser.

1app(Pipeline::class)
2 ->send($a = 0)
3 ->through([
4 Increment::class,
5 Increment::class,
6 Increment::class,
7 ]);

Un Pipe est un simple class devant implémenter une méthode handle.

1class Increment
2{
3 public function handle(int $a, Closure $next)
4 {
5 $a++;
6 
7 return $next($a);
8 }
9}

Chaque Pipe envoyé dans la méthode through sera instancié successivement et recevra notre variable $a précédemment transmise à la méthode send.

Tips, la méthode send n'accepte qu'un argument mais rien ne vous empêche d'envoyer un array pour le déconstruire dans votre Pipe !

Pour finir, plusieurs possibilités s'offrent à vous pour exécuter ce pipeline.

La méthode thenReturn permettra de récupérer directement le résultat de l'ensemble des Pipes.

1$result = app(Pipeline::class)
2 ->send($a = 0)
3 ->through([
4 Increment::class,
5 Increment::class,
6 Increment::class,
7 ])
8 ->thenReturn();
9 
10echo $result; // 3

Tandis que la méthode then permettra d'exécuter une closure sur le retour des Pipes.

1$result = app(Pipeline::class)
2 ->send($a = 0)
3 ->through([
4 Increment::class,
5 Increment::class,
6 Increment::class,
7 ])
8 ->then(fn($a) => $a * 10);
9 
10echo $result; // 30

Nous venons de voir que le pattern Pipeline offrait une nouvelle façon intéressante de factoriser notre code.

Étant une class à part entière, le Pipe devient un moyen judicieux d'encapsuler des brides de logiques métier.

Libre à vous d'utiliser un même Pipe dans plusieurs Pipeline ayant des finalités diverses et variées !

Mathieu De Gracia avatar
Mathieu De Gracia
Des fois, mon chat code à ma place 🐱

A lire

Autres articles de la même catégorie