Routing middleware attributes not available in request (Slim 4)

Hello. I have trouble with accessing current route in application’s service that is called from depenendcy container.

So, running following code on Apache + PHP-FPM:

<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use Slim\Factory\ServerRequestCreatorFactory;

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

$app = AppFactory::create();

$app->get('/', function (Request $request, Response $response, $args) {
    // HERE REQUEST HAVE ATTRIBUTES FILLED
    $response->getBody()->write("Hello world!");
    return $response;
});

$serverRequestCreator = ServerRequestCreatorFactory::create();
$request = $serverRequestCreator->createServerRequestFromGlobals();
$app->addRoutingMiddleware();
// HERE REQUEST DOES NOT HAVE ATTRIBUTES AT ALL
$app->run($request);

and following configuration:

  • PHP: 7.4.9
  • slim/slim: 4.11.0
  • slim/psr7: 1.6.1

Makes $request NOT HAVING attributes such as __routeParser__, __routingResults__, __route__ and __basePath__ in place where second // HERE... comment is placed, despite calling addRoutingMiddleware() just before $app->run().

I’m not sure if this is something valid or not, but all knowledge I’ve found in the Internet about accessing current route is about placing $app->addRoutingMiddleware() before $app->run()

I please for help.

1 Like

9 of 10 times it happens like this: you spend hours to find solution for your problem, finally when you’re desperate, you decide to write your own post/issue on github/discourse/IRC/you-name-it and ask others for help.

And just after you post it, you find a solution yourself! Bravo! :smiley:

So my solution (for offsprings) is like that:

Add simple app middleware that will bind current route from within it to the container, have a look:

// ...

$container = new League\Container\Container();
$container->defaultToShared();

$app = AppFactory::create(null, $container);

// To have current route object present in dependency container:
$app->add(function (ServerRequestInterface $request, RequestHandlerInterface $handler) use ($container) {
    $routeContext = RouteContext::fromRequest($request);
    $route = $routeContext->getRoute();
    $container->add(\Slim\Routing\Route::class, fn() => $route);

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

$app->get('/', function (Request $request, Response $response, $args) {
    $response->getBody()->write("Hello world!");
    return $response;
});

// ...

And it works!
I hope it will save someone’s time :wink: however - I’d love to find nicer solution - this one looks like hack.

Just a minor note: Since the request is context specific, as of Slim 4 all HTTP request/response related objects are no longer provided by the DI container. In practice, the request/response and routing objects should therefore normally be used directly (and preferably only there) in the HTTP specific (controller/action/handler) layer.