Symfony 2.2.1旧项目:在Doctrine EntityRepository中注入访问DIC服务
在Symfony 2.2.1的特定EntityRepository中注入服务的方案
针对你这个遗留项目的需求,我整理了两个靠谱的方案,都能实现只给特定EntityRepository注入服务/容器,不会影响到Entity本身:
方案一:自定义Repository工厂(推荐)
这个方法通过扩展Doctrine默认的Repository工厂,在创建目标Repository实例时自动注入服务,非常灵活,而且不会破坏原有代码结构。
步骤1:创建自定义Repository工厂
写一个继承自Doctrine默认工厂的类,在创建Repository时判断是否是目标类,是的话就注入服务:
namespace Your\Bundle\Repository; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Repository\DefaultRepositoryFactory; use Your\Bundle\Repository\YourTargetRepository; use Your\Bundle\Service\YourNeededService; class CustomRepositoryFactory extends DefaultRepositoryFactory { private $yourService; public function __construct(YourNeededService $yourService) { $this->yourService = $yourService; } protected function createRepository(EntityManagerInterface $entityManager, $entityName) { $repository = parent::createRepository($entityManager, $entityName); // 只给目标Repository注入服务 if ($repository instanceof YourTargetRepository) { $repository->setYourNeededService($this->yourService); } return $repository; } }
步骤2:给目标Repository添加setter方法
在你要注入服务的Repository里加一个setter,用来接收注入的服务:
namespace Your\Bundle\Repository; use Doctrine\ORM\EntityRepository; use Your\Bundle\Service\YourNeededService; class YourTargetRepository extends EntityRepository { private $yourNeededService; public function setYourNeededService(YourNeededService $service) { $this->yourNeededService = $service; } // 现在就能在Repository的方法里用这个服务了 public function someCustomQuery() { $data = $this->yourNeededService->fetchCriticalData(); // ... 你的业务逻辑 } }
步骤3:配置Symfony服务和Doctrine
在services.yml里注册自定义工厂服务:
services: your_bundle.custom_repository_factory: class: Your\Bundle\Repository\CustomRepositoryFactory arguments: - "@your_needed_service" # 替换成你要注入的服务ID your_needed_service: class: Your\Bundle\Service\YourNeededService # 你的服务配置
然后在config.yml里告诉Doctrine用这个自定义工厂:
doctrine: orm: # 其他ORM配置... repository_factory: your_bundle.custom_repository_factory
方案二:将Repository注册为服务
如果你的项目允许修改实体的映射配置,也可以直接把目标Repository注册成服务,通过构造或setter注入所需服务。
步骤1:注册Repository服务
在services.yml里把Repository注册为服务,注入EntityManager和需要的服务:
services: your_bundle.your_target_repository: class: Your\Bundle\Repository\YourTargetRepository arguments: - "@doctrine.orm.entity_manager" - "%your_target_entity_class%" # 比如 Your\Bundle\Entity\YourTargetEntity calls: - [setYourNeededService, ["@your_needed_service"]]
步骤2:修改实体的Repository配置
在你的实体类注解(或XML/YAML映射)里,把repositoryClass改成服务ID:
namespace Your\Bundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity(repositoryClass="your_bundle.your_target_repository") */ class YourTargetEntity { // ... 实体字段和映射 }
注意:这个方法在Symfony 2.2+Doctrine 2.3中是支持的,但如果你的项目里有其他Repository的特殊配置,可能需要测试兼容性。
不推荐的方式
不要用静态方法直接从容器获取服务,这种方式会让代码耦合容器,后续维护起来非常麻烦,完全违背了依赖注入的原则。
内容的提问来源于stack exchange,提问作者palmic
相关产品推荐
相关产品推荐

