Symfony bundle继承 - 如何覆盖/扩展服务类

时间:2016-12-06 09:00:08

标签: php symfony inheritance

在我的Symfony 2.8项目中,我使用bundle继承覆盖/扩展FOSUserBundle:自定义包中具有相同路径和名称的文件覆盖FOSUserBundle中的原始文件。 / p>

虽然这适用于控制器和翻译和视图等资源,但它似乎不适用于服务类。

例如,FOSUserBundle使用Resources\config\util.xml来定义fos_user.util.password_updater服务,以使用Util\PasswordUpdater.php中定义的类。

简单地将Util\PasswordUpdater.php添加到继承的包中不起作用。此文件将被忽略,捆绑包仍使用原始版本。

这是服务的缩进行为(因为原始服务定义仍然指向原始文件),或者我做错了什么?

覆盖/扩展服务的正确方法是什么?我找到了information,使用compiler pass是一般的最佳解决方案。但是,当已经使用bundle继承时,这也是真的吗?

2 个答案:

答案 0 :(得分:3)

要覆盖您需要在Bundle中创建CompilerPass的服务:

<?php

namespace AppBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Class OverrideServiceCompilerPass
 * @package Shopmacher\IsaBodyWearBundle\DependencyInjection\Compiler
 */
class OverrideServiceCompilerPass implements CompilerPassInterface
{

    /**
     * Overwrite project specific services
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $defNewService = $container->getDefinition('service.id.you.want.to.override');
        $defNewService ->setClass('AppBundle\Service\NewService');

    }
}

在Bundle文件中注册:

class AppBundle extends FOSUserBundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);

        $container->addCompilerPass(new OverrideServiceCompilerPass());
    }
}

然后将加载您的服务文件。在此文件中,您可以扩展原始服务文件和共享方法,也可以创建全新服务。

答案 1 :(得分:3)

  

我发现信息,使用编译器传递通常是最好的解决方案。但是,当已经使用bundle继承时,这也是真的吗?

是的,Compiler Pass是覆盖服务定义的最合适的解决方案。它是标准的Symfony DI问题,与bundle继承过程无关。

有时bundle也会在参数中定义类名。在这种情况下,您只需设置这些参数即可覆盖服务。但是这种技术是官方最佳实践not recommended,今天很少使用。