For some logging/monitoring i would like to get the current route path including placeholders.
If my route is /blog/{slug} and the request is to http://localhost/blog/foobar what i need is "/blog/{slug}"
In request listeners this value seem to not be inside the request object. I only find the resolved path which i am not interested in.
In Compiler passes I have the issue that any Router related service I try to get from the ContainerBuilder returns an exception. If i had the
What is a clean way to obtain this?
CodePudding user response:
For routes with one param:
$routeWithoutParam = substr($request->getRequestUri(),0,strrpos($request->getRequestUri(),'/'));
$routeParams = $request->attributes->get('_route_params');
$routeDefinition = $routeWithoutParam.'/{' . array_key_first($paramsArray) . '}';
echo $routeDefinition;
For routes with multiple params:
$routeParams = $request->attributes->get('_route_params');
$routeWithoutParam = '';
for ($i = 0; $i < count($routeParams); $i ) {
$routeWithoutParam = $i === 0
? substr($request->getRequestUri(), 0, strrpos($request->getRequestUri(), '/'))
: substr($routeWithoutParam, 0, strrpos($routeWithoutParam, '/'))
;
}
$routeDefinition = $routeWithoutParam.'/';
foreach (array_keys($routeParams) as $key => $param) {
$routeDefinition.= '{' . $param . '}' . ($key < count($routeParams)-1 ? '/' : '');
}
echo $routeDefinition;
CodePudding user response:
You can obtain the Router
and RouteCollection
, that holds all the routes in your app:
// src/Listener/RouteLoggerListener.php -- namespace and use ommited
class RouteLoggerListener implements EventSubscriberInterface
{
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var RouterInterface
*/
private $router;
public function __construct(LoggerInterface $logger, RouterInterface $router)
{
$this->logger = $logger;
$this->router = $router;
}
public static function getSubscribedEvents()
{
// Trigger after the RouterListener
return [KernelEvents::REQUEST => ['onKernelRequest', 50]];
}
public function onKernelRequest(RequestEvent $event)
{
if (!$event->isMainRequest()) {
return;
}
$request = $event->getRequest();
if (null == $request) {
return;
}
$matchedRoute = $request->attributes->get('_route');
if (null == $matchedRoute) {
// Bail gracefully
return;
}
$routeCollection = $this->router->getRouteCollection();
$route = $routeCollection->get($matchedRoute);
$this->logger->debug('Request route: '.$route->getPath());
}
}
Note: Using RouteCollection
at runtime is highly discouraged because it triggers a recompile. As indicated in this GitHub comment, the proper way to do it would be to use ConfigCache
while cache warming.