Symfony 5参数注入自动装配问题:控制器无法获取Manager
嘿,我帮你找出问题所在啦!你的错误主要来自services.yaml里的几个配置失误,还有对Symfony 5自动装配逻辑的小误解,咱们一步步来修正:
1. 首先是参数引用的低级错误
你在配置MailjetClient时,写错了参数名称:
App\Client\MailjetClient\: resource: '../src/Client/MailjetClient.php' arguments: $apikey: '%mailjet.host%' # 这里应该是%mailjet.apikey%,你之前定义的是apikey不是host! $apisecret: '%mailjet.port%' # 同理,这里要改成%mailjet.apisecret%
你在parameters里明明定义的是mailjet.apikey和mailjet.apisecret,结果引用的时候写成了host和port,Symfony找不到这些参数,自然没法完成注入。
2. 服务定义的语法用错了
针对单个类的服务定义,不需要用:结尾的语法(这种是给目录下多个类批量配置用的),正确写法应该直接用类的完整命名空间作为服务ID:
App\Client\MailjetClient: arguments: $apikey: '%mailjet.apikey%' $apisecret: '%mailjet.apisecret%'
另外,你在MailerManager的配置里引用了@client.mailjet这个别名,但你根本没给MailjetClient设置别名,所以要补上:
App\Client\MailjetClient: arguments: $apikey: '%mailjet.apikey%' $apisecret: '%mailjet.apisecret%' alias: 'client.mailjet' # 加上这个别名,让MailerManager能正确引用
3. 别重复定义服务,浪费自动装配的便利
你已经在全局配置里写了:
App\: resource: '../src/*' exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
这意味着Symfony会自动装配src/下所有符合条件的类,包括你的MailjetClient和MailerManager。但你又单独手动定义了这两个服务,这会导致冲突,反而让自动装配失效。
优化后的完整配置
其实只需要保留全局自动装配,**只手动配置需要注入参数的MailjetClient**就够了,MailerManager的依赖自动装配会帮你搞定:
parameters: # ... 保留你的其他参数 mailjet: apikey: '%env(MAILJET_APIKEY)%' apisecret: '%env(MAILJET_APISECRET)%' services: _defaults: autowire: true autoconfigure: true App\: resource: '../src/*' exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}' App\Controller\: resource: '../src/Controller' tags: ['controller.service_arguments'] # 只处理MailjetClient的参数注入,其他交给自动装配 App\Client\MailjetClient: arguments: $apikey: '%mailjet.apikey%' $apisecret: '%mailjet.apisecret%' alias: 'client.mailjet' # 如果不需要别名可以删掉,直接靠类型提示注入
最后补个小提示
Symfony 5的自动装配是根据构造函数的类型提示来自动匹配服务的,只要你的类在自动扫描范围内,不需要手动定义每个服务。像MailerManager只依赖MailjetClient,自动装配会自动找到MailjetClient的实例注入进去,完全不需要你手动配置它的服务定义。
这样修改后,你在控制器里注入MailerManager就不会报错啦!
内容的提问来源于stack exchange,提问作者Cornezuelo del Centeno

