Я хочу украсить класс Symfony UrlGenerator.
Symfony\Component\Routing\Generator\UrlGenerator: ~
my.url_generator:
class: AppBundle\Service\UrlGenerator
decorates: Symfony\Component\Routing\Generator\UrlGenerator
arguments: ['@my.url_generator.inner']
public: false
Я добавил это в services.yml, но мой класс AppBundle\Service\UrlGenerator игнорируется:
Я снова попробовал следующую конфигурацию.
config/services.yaml
parameters:
locale: 'en'
router.options.generator_class: AppBundle\Service\UrlGenerator
router.options.generator_base_class: AppBundle\Service\UrlGenerator
Тем не менее это не работает
Как украсить UrlGenerator в Symfony 4.2?






Я считаю, что вам нужно украсить Symfony\Component\Routing\Generator\UrlGeneratorInterface, потому что сервисы должны зависеть от интерфейса, а не от конкретной реализации (класса).
Я считаю, что проблема в том, что имя службы UrlGenerator — Symfony\Component\Routing\Generator\UrlGeneratorInterface, а не Symfony\Component\Routing\Generator\UrlGenerator (ср. этот код).
Во-вторых, когда вы декорируете сервис, декоратор возьмет имя сервиса. Так что вам не нужно изменять router.options.generator_class.
Попробуйте с этой конфигурацией:
my.url_generator:
class: AppBundle\Service\UrlGenerator
decorates: Symfony\Component\Routing\Generator\UrlGeneratorInterface
arguments: ['@my.url_generator.inner']
Установка public на false скорее всего не нужна, так как на Symfony4/Flex это должно быть значение по умолчанию.
Обновление для комментариев: оформленный сервиз может выглядеть так:
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);
}
}
Я тоже хотел бы знать ответ на эти точные вопросы
UrlGeneratorInterface загружается Symfony, ваш сервис, скорее всего, всегда будет определен позже. Насчет декорирования, это другой механизм, где вы будете заменять сервис на свой, но можете передать метод "внутреннему" сервису. Я обновлю свой ответ примером кода, так как не могу опубликовать его в комментариях.
Правильный ответ: вы не должны украшать UrlGeneratorInterface. Вы должны украсить службу «маршрутизатор». Проверьте здесь: 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);
}
}
Означает ли это, что определенная мной служба должна быть загружена после "Symfony\Component\Routing\Generator\UrlGeneratorInterface"? Кроме того, позволяет ли декорирование переопределить только 1 конкретный метод класса? Или я должен вместо этого попытаться заменить сервис/класс?