phpslimslim-4

Accessing route parameters in middleware in Slim 4


I would like to know how I can access route parameter in a middleware in Slim 4.

Provided I define a route with placeholder and attached middleware:

<?php

// ...

$app
    ->get('/{userId}', Controller::class)
    ->add(Middleware::class);

I would like to access value of {userId} from middleware before the controller is inovked:

class Middleware
{
    function __invoke($request, $handler)
    {
        // Resolve user ID in this scope?..
        return $handler->handle($request);
    }
}

I know that in Slim 3 we could do it accessing attributes of request object, however, it does not work in Slim 4. The attributes of route object contain the following entries:

Non of these seems to contain parameters.


Solution

  • What you need is documented here. You can create the route context, and the route object itself, using the request object in your middleware. Just keep in mind that you have to add routing middleware for this to work. Here is an example:

    <?php                                                                                                                                                                    
    use Slim\Factory\AppFactory;                                                                                                                                             
    use Slim\Routing\RouteContext;                                                                                                                                           
    
    require __DIR__ . '/../vendor/autoload.php';                                                                                                                             
    
    // Create App                                                                                                                                                            
    $app =  AppFactory::create();                                                                                                                                            
    
    Class Middleware                                                                                                                                                         
    {                                                                                                                                                                        
        function __invoke($request, $handler)                                                                                                                                
        {                                                                                                                                                                    
            $routeContext = RouteContext::fromRequest($request);                                                                                                             
            $route = $routeContext->getRoute();                                                                                                                              
            // Resolve user ID in this scope                                                                                                                                 
            $id = $route->getArgument('id');                                                                                                                                 
            $response = $handler->handle($request);                                                                                                                          
            $response->getBody()->write("Route parameter value (in middleware): {$id}");                                                                                     
            return $response;                                                                                                                                                
        }                                                                                                                                                                    
    }                                                                                                                                                                        
    
    $app->get('/{id}', function($request, $response, $args) {                                                                                                                
        return $response;                                                                                                                                                    
    })->add(Middleware::class);                                                                                                                                              
    
    $app->addRoutingMiddleware();                                                                                                                                            
    
    // Run app                                                                                                                                                               
    $app->run();
    

    Now try visiting /1 or /2 and you see the middleware is aware of the parameter value.