Symfony3.4 LTS升级:Translator扩展服务获取全局应用容器问题
在Symfony 3.4中为自定义Translator获取容器的解决方案
你遇到的问题是Symfony版本升级后的典型变化:Symfony 2.x里FrameworkBundle的Translator类继承了ContainerAware,所以能直接通过$this->container访问容器,但到了Symfony 3.4,这个类已经不再持有容器引用,直接调用会抛出未定义属性的错误。下面给你两种可行的解决办法,推荐第二种更符合依赖注入原则的方式:
方法1:注入完整的服务容器
如果确实需要全局容器(不推荐,但满足你的需求),可以通过构造函数注入ContainerInterface:
步骤1:修改自定义Translator类
更新类的构造函数,添加容器参数,并确保正确传递父类所需的参数:
<?php namespace AppBundle\Translation; use Symfony\Bundle\FrameworkBundle\Translation\Translator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Translation\MessageFormatterInterface; use Symfony\Component\Translation\TranslatorInterface; class TenantAwareTranslator extends Translator { private $container; // 严格匹配Symfony 3.4父类Translator的构造函数参数 public function __construct( TranslatorInterface $translator, MessageFormatterInterface $formatter, string $locale = null, ContainerInterface $container ) { parent::__construct($translator, $formatter, $locale); $this->container = $container; } protected function loadCatalogue($locale) { parent::loadCatalogue($locale); // 现在可以正常获取容器内的服务了 $twig = $this->container->get('twig'); // ... 你的租户数据库翻译加载逻辑 } }
步骤2:配置服务定义
在app/config/services.yml(或对应的XML/PHP配置)中,注入容器到自定义Translator服务:
services: app.tenant_aware_translator: class: AppBundle\Translation\TenantAwareTranslator arguments: - '@translator.default' # 父类依赖的基础Translator实例 - '@translation.formatter.message' # 消息格式化器依赖 - '%locale%' # 应用默认语言 - '@service_container' # 注入全局服务容器 tags: - { name: translator } # 标记为翻译服务,让Symfony识别
方法2:直接注入所需的Twig服务(推荐)
依赖注入的最佳实践是只注入实际需要的服务,而非整个容器,这样代码更清晰,也更容易测试和维护:
步骤1:修改自定义Translator类
直接注入Twig的Environment类:
<?php namespace AppBundle\Translation; use Symfony\Bundle\FrameworkBundle\Translation\Translator; use Symfony\Component\Translation\MessageFormatterInterface; use Symfony\Component\Translation\TranslatorInterface; use Twig\Environment; class TenantAwareTranslator extends Translator { private $twig; public function __construct( TranslatorInterface $translator, MessageFormatterInterface $formatter, string $locale = null, Environment $twig ) { parent::__construct($translator, $formatter, $locale); $this->twig = $twig; } protected function loadCatalogue($locale) { parent::loadCatalogue($locale); // 直接使用注入的Twig实例,无需再从容器获取 // ... 你的租户数据库翻译加载逻辑 } }
步骤2:配置服务定义
在services.yml中注入Twig服务:
services: app.tenant_aware_translator: class: AppBundle\Translation\TenantAwareTranslator arguments: - '@translator.default' - '@translation.formatter.message' - '%locale%' - '@twig' # 直接注入Twig服务实例 tags: - { name: translator }
关键说明
- Symfony 3.x开始逐步移除框架类对
ContainerAware的依赖,核心目的是降低代码耦合,让依赖关系更明确。 - 如果你的自定义Translator需要替换Symfony默认的翻译服务,可以将服务ID改为
translator,或者调整标签优先级,具体取决于你的应用配置逻辑。
内容的提问来源于stack exchange,提问作者Alexey
相关产品推荐
相关产品推荐

