symfony 7.3 依赖注入默认启用自动装配,控制器通过构造函数类型提示+private readonly即可自动注入服务,无需手动配置或调用$container->get()。

Symfony 7.3 的依赖注入(DI)不是“配置一堆 YAML 再手动写引用”,而是开箱即用的自动装配 + 显式控制。只要类有明确类型提示、服务已注册,容器就能在构造时自动塞进所需对象——不需要 new,也不需要 $container->get()。
从一个控制器开始:构造函数注入
这是最常用也最推荐的方式。Symfony 默认把控制器当作服务管理,你只需声明依赖,框架自动完成注入。
- 确保你的控制器类位于
src/Controller/下,且继承AbstractController - 在构造函数中用接口或具体类类型提示所需服务,加上
private readonly声明(PHP 8.1+ 推荐) - 不需要在
services.yaml中额外配置,autowiring 默认开启
示例:
<?php // src/Controller/PaymentController.php
namespace App\Controller;
use App\Service\PaymentProcessor;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Psr\Log\LoggerInterface;
class PaymentController extends AbstractController
{
public function __construct(
private readonly PaymentProcessor $processor,
private readonly LoggerInterface $logger
) {
}
public function process(): Response
{
$this->logger->info('Starting payment flow');
$this->processor->handle();
return $this->json(['status' => 'ok']);
}
}
自定义服务:无需配置也能被自动注入
只要你把服务类放在 src/ 目录下,并使用标准命名空间(如 App\Service\),Symfony 7.3 就能通过反射识别其构造参数并自动绑定。
- 服务类本身不需实现任何接口,但建议用接口类型提示(如
LoggerInterface),便于替换实现 - 如果某个依赖无法自动解析(比如多个同类型服务),才需要在
config/services.yaml中加bind:或显式arguments: - 私有属性 +
readonly是安全写法,避免意外修改
命令行命令同样支持注入
Symfony 命令类(继承 Command)也是容器服务,天然支持构造函数注入。
- 不要在
execute()方法里调用$this->getContainer()->get('...') - 把业务逻辑抽到独立服务中,在命令构造函数里注入它
- 这样命令只负责调度,服务可复用于控制器、事件监听器等场景
示例:
<?php // src/Command/ExportUsersCommand.php
namespace App\Command;
use App\Service\UserExporter;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'app:export-users')]
class ExportUsersCommand extends Command
{
public function __construct(private readonly UserExporter $exporter)
{
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->exporter->toCsv();
$output->writeln('Export completed.');
return Command::SUCCESS;
}
}
验证和调试小技巧
遇到注入失败时,别急着改代码,先用内置命令定位问题:
-
php bin/console debug:container查看所有可用服务名和类名 -
php bin/console debug:container --types按接口类型筛选(比如查所有LoggerInterface实现) -
php bin/console debug:container app.command.export_users看某个命令的具体定义和依赖 - 错误信息通常会直接指出哪个参数无法解析,比如 “Cannot autowire service … no such service exists” —— 这说明类没被扫描到或命名空间不对











