symfony 6.x 中 autowire 是默认行为,_defaults 块不可删除,否则导致自动装配全局关闭、服务无法自动发现及控制器参数注入失败;必须保留 autowire: true、autoconfigure: true 和 public: false,并正确定义 resource 与 controllers 标签。

自动装配在 Symfony 6.x 中不是可选项,而是默认行为;autowire: true 已写死在 services.yaml 的 _defaults 块里,手动关掉反而需要额外操作。
services.yaml 的 defaults 块为什么不能删
新项目生成的 config/services.yaml 里,_defaults 是容器行为的总开关。删掉它会导致:
-
autowire和autoconfigure全局关闭 → 所有服务构造函数参数都得手动写arguments - 所有服务默认变成
public: false,但控制器方法参数注入(MyService $service)会直接失败,报Cannot autowire service -
resource: '../src/'失效 →App\下的服务不再被自动发现
标准 _defaults 写法(别改缩进、别漏冒号):
services:
_defaults:
autowire: true
autoconfigure: true
public: false
App\:
resource: '../src/'
什么时候必须手动写 arguments
自动装配只解决「类型提示明确 + 容器里有唯一匹配服务」的问题。以下情况必须显式配 arguments:
- 构造函数参数是标量(
string、int、bool),比如__construct(string $apiHost) - 接口有多个实现类,容器不知道选哪个,比如
LoggerInterface对应Monolog\Logger和自定义FileLogger - 需要传入表达式(
@=service_container)或参数(%kernel.environment%) - 某服务需要跳过自动装配,强制指定某个具体实例
示例:给接口指定具体实现
App\Service\PaymentProcessor:
arguments:
$logger: '@monolog.logger.payment'
controller.service_arguments 标签的作用
这个标签不是可有可无的装饰,它是控制器方法参数注入的硬性前提。没有它,即使你写了 public function index(MyService $service),也会报 Controller "index" has no route 或参数解析失败。
它必须出现在 controllers 子块下(注意缩进层级):
controllers:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
常见错误:
- 把
tags写在App\:下 → 标签不生效,控制器注入全挂 - 漏掉
resource行 → 控制器类根本没被扫描,更别说注入 - 用
public: true替代该标签 → 没用,这是两回事
自动装配失败时的调试路径
遇到 Cannot autowire service,优先检查这三处:
- 目标类是否在
App\命名空间下?不在则不会被resource: '../src/'扫到 - 构造函数参数类型是否拼错?比如写了
MailrInterface而不是MailerInterface - 对应的服务 ID 是否存在?运行
php bin/console debug:container --types查看已注册类型
别急着加 arguments —— 先确认是不是命名空间、类名、类型提示这三个地方之一打错了字母。











