Symfony3.4升级4.4(无flex)报tactician.commandbus服务编译错误
Symfony 3.4升级4.4(非Flex结构)tactician.commandbus服务被移除/内联报错修复
报错根因
Symfony 4.0起容器编译阶段默认会内联移除两类服务:未显式声明public: true、且未被其他服务通过类型引用/自动装配标记为依赖的服务。
你之前的配置不生效,核心问题是只给League\Tactician\CommandBus类名加了指向tactician.commandbus的别名,没有直接修改tactician bundle注册的原服务的公开属性;加上jms/di-extra-bundle的@Inject注解是按服务ID直接从容器拉取服务,不会被容器的依赖引用检测识别,最终原服务被编译优化删掉,别名指向空就触发报错。
可落地方案(按改造成本从低到高排序)
方案1:最小改动修复(无需改业务代码,适配旧目录结构)
直接在项目全局服务配置(通常是app/config/services.yml,保证配置加载顺序在TacticianBundle配置之后)中,显式覆盖你用到的所有按ID注入的服务,强制标记为public:
# 不要放在带autowire的_defaults块内部,单独声明覆盖第三方bundle服务 tactician.commandbus: class: League\Tactician\CommandBus public: true tactician.commandbus.mngmt: class: League\Tactician\CommandBus public: true # 其他用@DI\Inject按ID注入的服务同理,一起标记public即可 monolog.logger: public: true app.services.mngmt_service: public: true
配置写完执行缓存清理命令即可生效:
php bin/console cache:clear --env=dev php bin/console cache:clear --env=prod
注意:如果你的配置文件开启了
autowire: true,上述服务覆盖块要和_defaults块平级,不要嵌套在里面,避免触发重复定义报错。
方案2:长期兼容修复(适配后续Symfony版本升级,无需维护public服务列表)
jms/di-extra-bundle在Symfony 4.4+的兼容性弱于框架原生DI,建议直接替换注解注入为原生构造函数绑定,一劳永逸解决同类服务内联问题:
- 先在
services.yml中配置参数绑定,区分两个同类型的CommandBus实例:services: _defaults: autowire: true autoconfigure: true public: false # 原生推荐服务默认私有,靠类型注入不需要公开 bind: # 按参数名绑定对应实例,和控制器构造函数参数名对应即可 CommandBus $commandBus: '@tactician.commandbus' CommandBus $mngmtCommandBus: '@tactician.commandbus.mngmt' - 精简控制器代码,删除整套
@DI\InjectParams注解,去掉手动注入ContainerInterface的逻辑(AbstractFOSRestController已经自带容器注入能力,不需要手动传参):class MngmtController extends AbstractFOSRestController { private CommandBus $commandBus; private CommandBus $mngmtCommandBus; private LoggerInterface $logger; private MngmtService $mngmtService; public function __construct( CommandBus $commandBus, CommandBus $mngmtCommandBus, LoggerInterface $logger, MngmtService $mngmtService ) { $this->commandBus = $commandBus; $this->mngmtCommandBus = $mngmtCommandBus; $this->logger = $logger; $this->mngmtService = $mngmtService; } }
这种写法下容器编译时会自动识别构造函数里的依赖引用,不会把对应服务内联移除,不需要手动给服务加public属性,后续升级Symfony 5/6版本也不会出现同类注入报错。
之前配置无效的原因说明
你之前写的:
League\Tactician\CommandBus: alias: 'tactician.commandbus' public: true
本质是给类名创建了一个新的公开别名,指向原tactician.commandbus服务,但原服务本身因为没有被依赖检测标记为被使用,还是会被容器内联删除,最终别名指向不存在的服务,报错不会消失。
内容的提问来源于stack exchange,提问作者user_fullstack
相关产品推荐
相关产品推荐

