Symfony Routing

Under the hood


Confoo Montreal,
February 24th, 2022


© David Buchmann







David Buchmann - david@liip.ch

PHP Engineer, Liip AG, Switzerland

We are hiring: https://liip.ch/jobs

var
`-- www
    `-- htdocs
        |-- index.htm
        |-- about.htm
        `-- news.htm
            

What about...

Front controller

RewriteRule ^(.*)$ app.php [QSA,L]
            

Routing

What PHP code to call for an URL?

switch($path) {
    case '/':
        return $controller->renderHomepage();
    case '/about':
        return $controller->renderAbout();
    default:
        return $controller->render404();
}
            


What about /product/{id} ?


Regular Expressions!


What about flexibility and efficiency?


...


Use an existing library!

The Symfony Routing component

public interface RequestMatcherInterface
{
    /**
     * @return array<string, string>
     */
    public function matchRequest(
        Request $request
    ): array;
}

The default router

Define routes

Caching

Optimizations

Optimizations: Group routes

/foo/x/{id}


/foo/y/{id}

/bar/baz
            
/foo
+---/x/
|   `--{id}
`---/y/
    `--{id}
/bar/baz
            

Tweaks in your application

Providing Context

$context = $this->router->getContext();

$context->setHost('example.com');
$context->setScheme('https');
$context->setBaseUrl('my/path');

$this->router->generate(...);
            
Symfony documentation

Custom router implementation

Routing in the Symfony Framework

Route sources

Custom loader: FOSRestBundle

                # app/config/routing.yml
                product:
                    type: rest
                    resource: AppBundle\Controller\ProductController
            

Custom Routers: Multilanguage

JMSI18nRoutingBundle

# routing.yml
homepage:
    path:  /welcome
    defaults: { _controller: MyWebsiteBundle:Frontend:index }

# translations/routes.de.yml
homepage: /willkommen

BeSimpleI18nRoutingBundle

type: be_simple_i18n
...
homepage:
    locales:
        en: /welcome
        de: /willkommen
    defaults: { _controller: MyWebsiteBundle:Frontend:index }

CMF DynamicRouter

CMF ChainRouter

Combine several routers

Look Beyond the Horizon

Interact with the route matching

FOSHttpCacheBundle hash listener

function onKernelRequest(GetResponseEvent $event) {
  $accept = $event->getRequest()
    ->headers->get('accept');
  if ('user-context-hash' !== $accept) return;
  $hash = $this->hashGenerator->generateHash();
  $response = new Response('', 200, array(
    $this->hashHeader => $hash,
    'Content-Type' => 'user-context-hash',
  ));
  $event->setResponse($response);
}
            

LiipThemeBundle:
Theme specific controllers

            my_route:
                path: /welcome
                defaults:
                    _controller: my_service:fooAction
                    theme_controllers:
                        a: my_other_service:fooAction
                        b: App:Other:foo
            
function onKernelRequest(GetResponseEvent $event) {
    $request = $event->getRequest();
    $theme = $this->activeTheme->getName();
    $controllers = $request->attributes
        ->get('theme_controllers');
    if (isset($controllers[$theme])) {
        $request->attributes->set(
            '_controller',
            $controllers[$theme]
        );
    }
}
            

Upcast controller arguments with ParamConverter

https://symfony.com/doc/current/components/http_kernel.html

ParamConverter



Questions / Input / Feedback ?


Twitter: @dbu