Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Fetching contributors…
Cannot retrieve contributors at this time
139 lines (119 sloc) 5.32 KB
* This file is part of the Symfony package.
* (c) Fabien Potencier <>
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
namespace Symfony\Component\HttpKernel\EventListener;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RequestContextAwareInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
* Initializes the context from the request and sets request attributes based on a matching route.
* @author Fabien Potencier <>
class RouterListener implements EventSubscriberInterface
private $matcher;
private $context;
private $logger;
* Constructor.
* @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher
* @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface)
* @param LoggerInterface|null $logger The logger
* @throws \InvalidArgumentException
public function __construct($matcher, RequestContext $context = null, LoggerInterface $logger = null)
if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) {
throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
if (null === $context && !$matcher instanceof RequestContextAwareInterface) {
throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.');
$this->matcher = $matcher;
$this->context = $context ?: $matcher->getContext();
$this->logger = $logger;
* Sets the current Request.
* The application should call this method whenever the Request
* object changes (entering a Request scope for instance, but
* also when leaving a Request scope -- especially when they are
* nested).
* @param Request|null $request A Request instance
public function setRequest(Request $request = null)
if (null !== $request) {
public function onKernelRequest(GetResponseEvent $event)
$request = $event->getRequest();
// initialize the context that is also used by the generator (assuming matcher and generator share the same context instance)
// we call setRequest even if most of the time, it has already been done to keep compatibility
// with frameworks which do not use the Symfony service container
if ($request->attributes->has('_controller')) {
// routing is already done
// add attributes based on the request (routing)
try {
// matching a request is more powerful than matching a URL path + context, so try that first
if ($this->matcher instanceof RequestMatcherInterface) {
$parameters = $this->matcher->matchRequest($request);
} else {
$parameters = $this->matcher->match($request->getPathInfo());
if (null !== $this->logger) {
$this->logger->info(sprintf('Matched route "%s" (parameters: %s)', $parameters['_route'], $this->parametersToString($parameters)));
$request->attributes->set('_route_params', $parameters);
} catch (ResourceNotFoundException $e) {
$message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo());
throw new NotFoundHttpException($message, $e);
} catch (MethodNotAllowedException $e) {
$message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getPathInfo(), strtoupper(implode(', ', $e->getAllowedMethods())));
throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e);
private function parametersToString(array $parameters)
$pieces = array();
foreach ($parameters as $key => $val) {
$pieces[] = sprintf('"%s": "%s"', $key, (is_string($val) ? $val : json_encode($val)));
return implode(', ', $pieces);
public static function getSubscribedEvents()
return array(
KernelEvents::REQUEST => array(array('onKernelRequest', 32)),
Jump to Line
Something went wrong with that request. Please try again.