You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,建议直接替换注解注入为原生构造函数绑定,一劳永逸解决同类服务内联问题:

  1. 先在services.yml中配置参数绑定,区分两个同类型的CommandBus实例:
    services:
        _defaults:
            autowire: true
            autoconfigure: true
            public: false # 原生推荐服务默认私有,靠类型注入不需要公开
    
        bind:
            # 按参数名绑定对应实例,和控制器构造函数参数名对应即可
            CommandBus $commandBus: '@tactician.commandbus'
            CommandBus $mngmtCommandBus: '@tactician.commandbus.mngmt'
    
  2. 精简控制器代码,删除整套@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 07:24:15