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 $requestNOT 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()…
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!
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 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.