Middleware

Middleware is code that runs around a route handler — before it, after it, or both. Think of your application as an onion: the incoming request passes through each layer of middleware from the outside in, finally reaching the route handler at the core. The response the handler returns then travels back out through the same layers, in reverse order, before it's sent to the browser.

Mental model: Request in → Middleware 1 → Middleware 2 → Route handler → Middleware 2 → Middleware 1 → Response out. Each middleware gets a chance to inspect or modify things on the way in and on the way out.

Writing a Simple Middleware

In Slim, a middleware is simply a callable that receives the $request and a $handler (the next layer, which could be another middleware or the route itself). It must call $handler->handle($request) to pass control onward, and it must return a response.

<?php
$exampleMiddleware = function ($request, $handler) {
    // Code here runs BEFORE the route handler
    $response = $handler->handle($request);

    // Code here runs AFTER the route handler, before the response goes out
    return $response;
};

The order of the two comments matters: everything above the call to $handler->handle() runs on the way in, and everything below it runs on the way out — after the route (or the next middleware) has already produced a response.

Adding Middleware to a Single Route

You can attach a middleware to just one route by chaining ->add() onto the route definition. This is useful when only one specific endpoint needs the extra behavior.

<?php
$app->get('/profile', function ($request, $response) {
    $response->getBody()->write('Your profile');
    return $response;
})->add($exampleMiddleware);

Adding Middleware Application-Wide

To run a middleware on every request, add it to the $app object itself with $app->add(), usually right after the app is created.

<?php
require __DIR__ . '/../vendor/autoload.php';

$app = \Slim\Factory\AppFactory::create();

// Runs for every single route in the app
$app->add($exampleMiddleware);
Order matters: Middleware added with $app->add() runs in a "last in, first out" order on the way in — the last middleware added is the first one the request hits.

Practical Example: A Logging Middleware

A common real-world use of middleware is logging every incoming request — recording the HTTP method and the path before the route handler even runs.

<?php
$loggingMiddleware = function ($request, $handler) {
    $method = $request->getMethod();
    $path = $request->getUri()->getPath();

    // Record it however you like: error_log(), a file, a database table...
    error_log("[{$method}] {$path}");

    return $handler->handle($request);
};

$app->add($loggingMiddleware);

Because this middleware is added directly to $app, every request — no matter which route it matches — gets logged automatically, without repeating this code in every handler.

Slim's Built-in Middleware

Slim ships with a couple of important middleware classes that are commonly added near the top of your app's setup, right after the app is created:

MiddlewareWhat it does
RoutingMiddlewarePerforms the actual route matching, so route information is available to any middleware added afterward
ErrorMiddlewareCatches exceptions and turns them into proper error responses instead of raw PHP errors
<?php
$app->addRoutingMiddleware();
$app->addErrorMiddleware(true, true, true);
Next up: Now that you can wrap routes with shared behavior, learn how to organize related routes together with Route Groups.