php 60 lines · 9 steps

Building an onion middleware pipeline in PHP

A Pipeline folds a list of middleware into nested closures so each layer wraps the next around a final destination.

Explained by highlit
1<?php
2 
3namespace App\Http;
4 
5use Closure;
6use Psr\Http\Message\ResponseInterface;
7use Psr\Http\Message\ServerRequestInterface;
8 
9interface Middleware
10{
11 public function handle(ServerRequestInterface $request, Closure $next): ResponseInterface;
12}
13 
14final class Pipeline
15{
16 private array $middleware = [];
17 
18 public function __construct(private readonly Closure $destination)
19 {
20 }
21 
22 public function pipe(Middleware ...$middleware): self
23 {
24 array_push($this->middleware, ...$middleware);
25 
26 return $this;
27 }
28 
29 public function handle(ServerRequestInterface $request): ResponseInterface
30 {
31 $stack = array_reduce(
32 array_reverse($this->middleware),
33 function (Closure $next, Middleware $layer): Closure {
34 return fn (ServerRequestInterface $request): ResponseInterface
35 => $layer->handle($request, $next);
36 },
37 $this->destination,
38 );
39 
40 return $stack($request);
41 }
42}
43 
44final class AuthenticateMiddleware implements Middleware
45{
46 public function __construct(private readonly TokenGuard $guard)
47 {
48 }
49 
50 public function handle(ServerRequestInterface $request, Closure $next): ResponseInterface
51 {
52 $token = $request->getHeaderLine('Authorization');
53 
54 if (! $user = $this->guard->resolve($token)) {
55 throw new UnauthorizedException('Missing or invalid bearer token.');
56 }
57 
58 return $next($request->withAttribute('user', $user));
59 }
60}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Reducing over a reversed list turns a flat array of layers into correctly ordered nested calls.
  2. 2Passing $next as a closure lets each middleware decide whether, and with what, to continue.
  3. 3Returning a request with added attributes threads state forward without mutating shared state.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Building an onion middleware pipeline in PHP — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code