Symfony 4.2 - 如何装饰UrlGenerator

7

我希望对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

仍然不起作用

如何在Symfony 4.2中装饰UrlGenerator

3个回答

6

正确的答案是:您不应该装饰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);
    }
}

不起作用 参数#1($routeGenerator)必须是类型为Sonata\AdminBundle\Route\RouteGeneratorInterface的对象,但给定的是Symfony\Cmf\Component\Routing\ChainRouter - ManBehindTheCurtain
参数#1($routeGenerator)的类型必须是Sonata\AdminBundle\Route\RouteGeneratorInterface,但实际传递了Symfony\Cmf\Component\Routing\ChainRouter。 - undefined

3
我认为问题在于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);
    }
}

1
这是否意味着我定义的服务必须在 "Symfony\Component\Routing\Generator\UrlGeneratorInterface" 之后加载?此外,装饰器是否允许我仅覆盖一个特定的类方法?还是应该尝试替换服务/类? - mr1031011
我也想知道这些确切问题的答案。 - code_gamer
1
UrlGeneratorInterface由Symfony加载,您的服务很可能总是在其后定义。关于装饰,这是一种不同的机制,您将用自己的服务替换服务,但是您可以将方法传递给“内部”服务。我会更新我的答案,并提供一个代码示例,因为我不能在评论中发布它。 - romaricdrigon

1
我相信你需要装饰 Symfony\Component\Routing\Generator\UrlGeneratorInterface,因为服务应该依赖于接口而不是特定的实现(类)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接