Symfony 4.0:TranslatorInterface在非控制器类无法自动注入求助
你提到在控制器中通过构造函数自动注入TranslatorInterface和LoggerInterface完全正常,但在自定义的MunicipalityValidator类中做同样的操作时,却遇到了参数不足的错误:
FatalThrowableError Type error: Too few arguments to function App\Validator\MunicipalityValidator::__construct(), 0 passed in /var/www/html/sf4proj/src/Factory/MunicipalityFactory.php on line 34 and exactly 2 expected
先看一下你的自定义类代码:
class MunicipalityValidator { private $_translator; private $_validator; public function __construct(TranslatorInterface $translator, ValidatorInterface $validator) { $this->_translator = $translator; $this->_validator = $validator; } //... }
问题原因
核心问题是:你的MunicipalityValidator类没有被Symfony的服务容器接管。
Symfony的控制器之所以能自动注入依赖,是因为框架默认会把控制器自动注册为服务,并且开启了自动注入(Autowiring)。但自定义类(比如你的Validator类)如果没有被配置为服务,Symfony的容器就不知道如何为它自动解析依赖。
而你在MunicipalityFactory.php的第34行,应该是直接通过new MunicipalityValidator()的方式实例化这个类——这种手动实例化的方式不会触发Symfony的自动注入逻辑,所以你没有传递构造函数需要的2个参数,自然就会报错。
解决方案
要解决这个问题,你需要让Symfony的服务容器管理MunicipalityValidator,并且通过依赖注入的方式获取它的实例,而不是手动new。
方案1:启用自动服务注册(推荐,Symfony 3.3+)
检查你的config/services.yaml文件,确保已经配置了自动注册src/目录下的类为服务:
services: _defaults: autowire: true # 开启自动注入 autoconfigure: true # 自动添加必要的服务标签(比如验证器相关的标签) public: false # 默认设置服务为私有,符合最佳实践 App\: resource: '../src/*' exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
这个配置会自动把src/下除了排除目录的所有类注册为服务,并且启用自动注入。
接下来,修改MunicipalityFactory,通过构造函数注入MunicipalityValidator,而不是手动实例化:
class MunicipalityFactory { private $municipalityValidator; // 通过构造函数注入依赖 public function __construct(MunicipalityValidator $municipalityValidator) { $this->municipalityValidator = $municipalityValidator; } public function someMethod() { // 使用注入的实例 $this->municipalityValidator->doSomething(); // 而不是 new MunicipalityValidator() } }
方案2:手动注册服务
如果你不想用自动注册,可以手动在services.yaml里注册MunicipalityValidator:
services: App\Validator\MunicipalityValidator: autowire: true # 开启这个服务的自动注入
之后同样需要在MunicipalityFactory中通过构造函数注入这个类的实例,不要手动new。
这样修改后,Symfony的服务容器会自动为MunicipalityValidator解析并注入TranslatorInterface和ValidatorInterface的实例,报错就会消失了。
内容的提问来源于stack exchange,提问作者M4kn4sh

