Symfony 3.4:如何为Doctrine的UserRepository注入服务(偏好Setter注入)
在Symfony 3.4中为EntityRepository实现Setter注入
在Symfony 3.4里,Doctrine的EntityRepository默认是由ORM自动实例化的,不会经过Symfony的服务容器,这就是你直接用构造/Setter注入没生效的核心原因。要解决这个问题,你需要把UserRepository注册为Symfony服务,并让Doctrine使用这个服务实例,而不是自动创建。下面是针对Setter注入的完整实现步骤:
1. 修改UserRepository代码
首先在你的仓库类中添加Setter方法,同时保留Doctrine要求的构造函数(必须传入EntityManagerInterface和ClassMetadata):
namespace AppBundle\Repository; use Doctrine\ORM\EntityRepository; use Your\Service\Namespace\YourNeededService; // 替换为你要注入的服务命名空间 class UserRepository extends EntityRepository { /** @var YourNeededService|null */ private $yourNeededService; // 必须保留这个构造函数,Doctrine依赖它初始化仓库 public function __construct( \Doctrine\ORM\EntityManagerInterface $em, \Doctrine\ORM\Mapping\ClassMetadata $class ) { parent::__construct($em, $class); } // Setter注入方法 public function setYourNeededService(YourNeededService $service): void { $this->yourNeededService = $service; } // 示例:使用注入服务的业务方法 public function performActionWithService() { if (!$this->yourNeededService) { throw new \RuntimeException('YourNeededService未注入UserRepository,请检查服务配置'); } // 调用注入的服务逻辑 $serviceResult = $this->yourNeededService->doSomething(); // ...后续业务处理 } }
2. 配置Symfony服务(services.yml)
在app/config/services.yml中,将UserRepository注册为服务,使用Doctrine的EntityManager作为工厂来创建实例,同时通过calls节点触发Setter注入:
services: app.user_repository: class: AppBundle\Repository\UserRepository # 使用EntityManager的getRepository方法作为工厂,确保Doctrine正确初始化仓库 factory: ['@doctrine.orm.entity_manager', getRepository] arguments: - AppBundle\Entity\User # 对应你的User实体类 # 调用Setter方法注入服务 calls: - [setYourNeededService, ['@your_needed_service']] # 替换为你的服务ID public: true # Symfony 3.4中服务默认私有,显式设为公开确保Doctrine能获取到
3. 关联User实体与仓库
确保你的User实体类通过注解或配置指定了这个仓库类:
namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository") */ class User { // ...实体属性和方法 }
4. 使用注入了服务的仓库
现在当你从EntityManager获取UserRepository时,得到的就是已经注入了目标服务的实例:
// 在控制器或其他服务中 $userRepo = $this->getDoctrine()->getRepository(User::class); $userRepo->performActionWithService(); // 可以正常使用注入的服务
为什么之前的尝试失败?
- 构造函数注入:Doctrine创建仓库时只会传入
EntityManager和ClassMetadata,自定义构造函数会导致ORM无法实例化仓库。 - 未注册服务:默认情况下Doctrine自动创建仓库实例,不会经过Symfony服务容器,所以注入逻辑不会被执行。
内容的提问来源于stack exchange,提问作者Matteo Busetto
相关产品推荐
相关产品推荐

