You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 17:48:15