I want to decorate the Symfony UrlGenerator
class.
Symfony\\Component\\Routing\\Generator\\UrlGenerator: ~
my.url_generator:
class: AppBund
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).
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);
}
}
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);
}
}