Search code examples
symfonyroutesdecoratorsymfony4router

Symfony 4: I decorated UrlGeneratorInterface, but it's not used, it uses CompiledUrlGenerator instead


I decorated UrlGeneratorInterface

app.decorator.url_generator:
    class: App\CoreBundle\Routing\Extension\UrlGenerator
    decorates: Symfony\Component\Routing\Generator\UrlGeneratorInterface
    arguments: ['@app.decorator.url_generator.inner']

but it's not used in cases where some bundle in example executes $this->generator->generate(), and I tracked what Symfony does through XDebug and CompiledUrlGenerator is used instead. I can see where this happens, namely in Symfony\Component\Routing\Router in getGenerator it specifically checks for CompiledUrlGenerator::class. But I don't want to override vanilla Symfony code. How am I supposed to override/decorate/extend which class in order for mine to be chosen always, as I have special parameters I need to add to the path. Thank you in advance!


Solution

  • I found it.

    app.decorator.router:
        class: App\CoreBundle\Routing\Extension\Router
        decorates: 'router.default'
        arguments: ['@app.decorator.router.inner']
    

    Decorating this actually makes all packages use your Router. And as the UrlGenerator it has the generate function which can be extended.

    EDIT: On request I provide the router class as well:

    class Router implements RouterInterface {
        protected $innerRouter;
        public function __construct(RouterInterface $innerRouter) {
            $this->innerRouter = $innerRouter;
        }
        public function setContext(RequestContext $context)
        {
            $this->innerRouter->setContext($context);
        }
        public function getContext()
        {
            return $this->innerRouter->getContext();
        }
        public function getRouteCollection()
        {
            return $this->innerRouter->getRouteCollection();
        }
        public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)
        {
            //add here to $parameters...
            return $this->innerRouter->generate($name, $parameters, $referenceType);
        }
        public function match($pathinfo)
        {
            $parameters = $this->innerRouter->match($pathinfo);
            //add here to $parameters...
            return $parameters;
        }
    }