Symfony 4.2 - How to decorate the UrlGenerator

后端 未结 3 1333
失恋的感觉
失恋的感觉 2021-01-05 14:52

I want to decorate the Symfony UrlGenerator class.

Symfony\\Component\\Routing\\Generator\\UrlGenerator: ~

my.url_generator:
    class: AppBund         


        
相关标签:
3条回答
  • 2021-01-05 14:55

    I believe you have to decorate the Symfony\Component\Routing\Generator\UrlGeneratorInterface, because the services should depend on the interface and not on a specific implementation (class).

    0 讨论(0)
  • 2021-01-05 15:05

    The right answer is : you shouldn't decorate UrlGeneratorInterface. You have to decorate 'router' service. Check here : https://github.com/symfony/symfony/issues/28663

    ** services.yml :

    services:
        App\Services\MyRouter:
            decorates: 'router'
            arguments: ['@App\Services\MyRouter.inner']
    

    ** MyRouter.php :

    <?php
    
    namespace App\Services;
    
    use Symfony\Component\Routing\RequestContext;
    use Symfony\Component\Routing\RouterInterface;
    
    class MyRouter implements RouterInterface
    {
        /**
         * @var RouterInterface
         */
        private $router;
    
        /**
         * MyRouter constructor.
         * @param RouterInterface $router
         */
        public function __construct(RouterInterface $router)
        {
            $this->router = $router;
        }
    
        /**
         * @inheritdoc
         */
        public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)
        {
            // Your code here
    
            return $this->router->generate($name, $parameters, $referenceType);
        }
    
        /**
         * @inheritdoc
         */
        public function setContext(RequestContext $context)
        {
            $this->router->setContext($context);
        }
    
        /**
         * @inheritdoc
         */
        public function getContext()
        {
            return $this->router->getContext();
        }
    
        /**
         * @inheritdoc
         */
        public function getRouteCollection()
        {
            return $this->router->getRouteCollection();
        }
    
        /**
         * @inheritdoc
         */
        public function match($pathinfo)
        {
            return $this->router->match($pathinfo);
        }
    }
    
    0 讨论(0)
  • 2021-01-05 15:11

    I believe the issue is that UrlGenerator service name is Symfony\Component\Routing\Generator\UrlGeneratorInterface, and not Symfony\Component\Routing\Generator\UrlGenerator (cf. this code).

    Secondly, when you decorate a service, the decorator will take the service name. So you should not need to modify router.options.generator_class.

    Try with this configuration:

    my.url_generator:
        class: AppBundle\Service\UrlGenerator
        decorates: Symfony\Component\Routing\Generator\UrlGeneratorInterface
        arguments: ['@my.url_generator.inner']
    

    Setting public to false is likely not needed, as on Symfony4/Flex it should be the default value.

    Update for comments: decorated service may look like this:

    class MyUrlGenerator implements UrlGeneratorInterface
    {
        private $originalUrlGenerator;
    
        public function __construct(UrlGeneratorInterface $innerUrlGenerator)
        {
            $this->originalUrlGenerator = $innerUrlGenerator;
        }
    
        public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)
        {
            // Maybe add your custom logic here... 
            // or completely override base method
    
            return $this->originalUrlGenerator->generate($name, $parameters, $referenceType);
        }
    }
    
    0 讨论(0)
提交回复
热议问题