Symfony 7中无法自动注入ValidatorService错误的解决方案
错误信息
Cannot autowire service "App\Core\Validator\ValidatorService": argument "$validators" of method "__construct()" references interface "App\Core\Validator\ValidatorInterface" but no such service exists. Did you create an instantiable class that implements this interface?
问题背景
我想在服务中注入一个接口的多个实例,已经创建了ValidatorInterface,并在LoginMessageValidator、WelcomeMessageValidator类中实现该接口,同时编写了ValidatorService类(代码如下)。项目使用自动装配,但出现上述错误,请问该如何解决?
相关代码
ValidatorInterface.php
<?php declare(strict_types = 1); namespace App\Core\Validator; use App\Core\MailStruct; interface ValidatorInterface { /** * support: checks if the validator class supports this type of email * * @param string $type * @return bool */ public function support(string $type): bool; /** * validate: checks if the request data is valid * * @param MailStruct $mail * @return void */ public function validate(MailStruct $mail): void; }
LoginMessageValidator.php
<?php declare(strict_types = 1); namespace App\Core\Validator; use App\Core\EmailType; use App\Core\MailStruct; use App\Core\Validator\ValidatorInterface; class LoginMessageValidator implements ValidatorInterface { public function support(string $type): bool { return $type === EmailType::LOGIN_EMAIL; } public function validate(MailStruct $mail): void { //dd(EmailType::LOGIN_EMAIL); } }
WelcomeMessageValidator.php
<?php declare(strict_types = 1); namespace App\Core\Validator; use App\Core\EmailType; use App\Core\MailStruct; use App\Core\Validator\ValidatorInterface; class WelcomeMessageValidator implements ValidatorInterface { public function support(string $type): bool { return $type === EmailType::WELCOME_EMAIL; } public function validate(MailStruct $mail): void { dd(EmailType::WELCOME_EMAIL); } }
ValidatorService.php(原错误版本)
<?php declare(strict_types = 1); namespace App\Core\Validator; use App\Core\MailStruct; use App\Core\Validator\ValidatorInterface; class ValidatorService { private ValidatorInterface $validators; public function __construct(ValidatorInterface $validators) { $this->validators = $validators; } public function validate(MailStruct $mail) { foreach($this->validators as $validator){ $validator->validate($mail); } } }
解决方法
1. 修改ValidatorService的类型声明
你当前的代码试图把多个验证器实例注入到单个ValidatorInterface类型的参数中,这不符合依赖注入规则——单个接口类型参数只会尝试注入一个实现类,而Symfony找不到直接对应ValidatorInterface的服务(因为接口本身不能实例化)。
需要把参数类型改成可迭代类型(iterable),同时调整属性类型:
<?php declare(strict_types = 1); namespace App\Core\Validator; use App\Core\MailStruct; use App\Core\Validator\ValidatorInterface; class ValidatorService { // 把单个接口类型改成可迭代类型 private iterable $validators; // 构造函数参数同样改为iterable public function __construct(iterable $validators) { $this->validators = $validators; } public function validate(MailStruct $mail) { // 遍历所有验证器,只执行支持当前邮件类型的验证逻辑 foreach($this->validators as $validator){ if ($validator->support($mail->type)) { // 假设MailStruct有type属性 $validator->validate($mail); } } } }
2. 确保Symfony自动收集所有实现类
如果使用Symfony 4.3及以上版本,自动装配会自动识别所有实现ValidatorInterface的服务,并将它们注入到iterable类型的参数中,无需额外配置。
如果是旧版本,需要在config/services.yaml中添加标签配置,让Symfony收集所有验证器:
services: # 给所有实现ValidatorInterface的类打上标签 _instanceof: App\Core\Validator\ValidatorInterface: tags: ['app.email_validator'] # 给ValidatorService注入所有带该标签的服务 App\Core\Validator\ValidatorService: arguments: $validators: !tagged_iterator app.email_validator
3. 验证逻辑优化(可选)
原代码的validate方法会遍历所有验证器并执行validate,但你的每个验证器都有support方法,应该只对当前邮件类型匹配的验证器执行验证,这样更符合设计意图(上面修改后的代码已经包含这部分逻辑)。
内容的提问来源于stack exchange,提问作者Templator Khan

