Symfony 6.1升级:如何从ServiceLocator获取Session与Doctrine接口
解决方案
一、获取EntityManagerInterface的正确方式
自定义继承AbstractController的控制器时,直接通过构造函数注入或者属性注入就能拿到EntityManagerInterface,完全不需要依赖容器的get方法:
1. 构造函数注入
use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; class BaseController extends AbstractController { protected EntityManagerInterface $em; public function __construct(EntityManagerInterface $em) { $this->em = $em; } }
2. 属性注入(Symfony 5.4+支持)
use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Contracts\Service\Attribute\Required; class BaseController extends AbstractController { protected EntityManagerInterface $em; #[Required] public function setEntityManager(EntityManagerInterface $em): void { $this->em = $em; } }
如果非要通过ServiceLocator获取,也可以在services.yaml里给控制器的服务定位器添加EntityManagerInterface,但这种方式不符合Symfony最佳实践,不推荐:
services: _defaults: autowire: true autoconfigure: true App\Controller\BaseController: calls: - method: setContainer arguments: - !service_locator '@Doctrine\ORM\EntityManagerInterface': '@Doctrine\ORM\EntityManagerInterface'
二、Session服务的问题解决
Symfony 5+中已经移除了session这个服务ID,取而代之的是SessionInterface。要让ServiceLocator能获取到它,需要在services.yaml里配置controller.services_locator参数,把SessionInterface添加进去:
parameters: controller.services_locator: Symfony\Component\HttpFoundation\Session\SessionInterface: '@Symfony\Component\HttpFoundation\Session\SessionInterface'
配置完成后,你就能在控制器里通过$this->container->get(SessionInterface::class)获取session实例,更推荐的方式还是直接注入到自定义基类控制器:
use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; class BaseController extends AbstractController { protected SessionInterface $session; protected EntityManagerInterface $em; public function __construct(SessionInterface $session, EntityManagerInterface $em) { $this->session = $session; $this->em = $em; } }
三、批量兼容旧代码的建议
如果项目里有大量$this->container->get('session')和$this->container->get('doctrine')的代码,除了上述配置,还可以:
- 用IDE的批量替换功能,把
$this->container->get('session')替换为$this->session(前提是基类已注入SessionInterface); - 把
$this->container->get('doctrine')->getManager()替换为$this->em。
这种方式既能快速完成代码迁移,又能符合Symfony 6的依赖注入规范。
内容的提问来源于stack exchange,提问作者Matthias Bakker
相关产品推荐
相关产品推荐

