Создайте репозиторий доктрины с зависимостями (инъекцией зависимостей) в ZF2

Я хочу создать репозиторий с жесткими зависимостями. Я нашел это сообщение в блоге Jurian Sluisman, но он предлагает получить репозиторий от менеджера сервиса и ввести его в службу там, где это необходимо.

Было бы намного лучше, если бы я смог получить свои пользовательские репозитории с инъецированными зависимостями, как обычно из моего экземпляра EntityManager или ObjectManager , используя метод getRepository :

 $objectManager->getRepository('My\Entity\Class'); 

Как я могу использовать getRepository конструктора в своих репозиториях и по-прежнему получать их как обычно из ObjectManager напрямую с getRepository метода getRepository ?

Doctrine использует класс Doctrine\ORM\EntityManagerInterface\DefaultRepositoryFactory для создания экземпляров репозитория. Если пользовательский завод не установлен, эта фабрика по умолчанию создается здесь в методе getRepositoryFactory в классе Doctrine\ORM\Configuration .

Определив настраиваемый repository_factory мы можем перезаписать этот заводский класс по умолчанию и добавить на фабрику настраиваемую логику, которая будет вводить жесткие зависимости:

Чтобы проиллюстрировать, как вы можете это сделать, я покажу пример, в котором заводский класс репозитория создает репозитории, зависящие от экземпляра ServiceLocator посредством ServiceLocator конструктора.

1) создать пользовательский заводский класс, который реализует интерфейс доктрины RepositoryFactory

Этот класс очень похож на класс доктрины DefaultRepositoryFactory .

 <?php namespace My\ORM\Repository; use Doctrine\Common\Persistence\ObjectRepository; use Doctrine\ORM\Repository\RepositoryFactory; use Doctrine\ORM\EntityManagerInterface; use Zend\ServiceManager\ServiceLocatorAwareInterface; use Zend\ServiceManager\ServiceLocatorAwareTrait; use Zend\ServiceManager\ServiceLocatorInterface; class CustomRepositoryFactory implements RepositoryFactory, ServiceLocatorAwareInterface { use ServiceLocatorAwareTrait; /** * @var ObjectRepository[] */ private $repositoryList = array(); /** * @var ServiceLocator */ protected $serviceLocator; /** * @param ServiceLocatorInterface $serviceLocator */ public function __construct(ServiceLocatorInterface $serviceLocator) { $this->serviceLocator = $serviceLocator; } /** * {@inheritdoc} */ public function getRepository(EntityManagerInterface $entityManager, $entityName) { $repositoryHash = $entityManager->getClassMetadata($entityName)->getName() . spl_object_hash($entityManager); if (isset($this->repositoryList[$repositoryHash])) { return $this->repositoryList[$repositoryHash]; } return $this->repositoryList[$repositoryHash] = $this->createRepository($entityManager, $entityName); } /** * @param EntityManagerInterface $entityManager The EntityManager instance. * @param string $entityName The name of the entity. * @return ObjectRepository */ private function createRepository(EntityManagerInterface $entityManager, $entityName) { /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */ $metadata = $entityManager->getClassMetadata($entityName); $repositoryClassName = $metadata->customRepositoryClassName ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName(); // Constructor injection, I check with subclass of but it is just an example if(is_subclass_of($repositoryClassName, ServiceLocatorAwareInterface::class)){ $serviceLocator = $this->getServiceLocator() $repository = new $repositoryClassName($entityManager, $metadata, $serviceLocator); }else{ $repository = new $repositoryClassName($entityManager, $metadata); } return $repository; } } 

2) Создайте завод для завода хранилища

 <?php namespace My\ORM\Repository\Factory; use My\ORM\Repository\CustomRepositoryFactory; use Zend\Cache\Storage\StorageInterface; use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\ServiceLocatorInterface; class CustomRepositoryFactoryFactory implements FactoryInterface { /** * @param ServiceLocatorInterface $serviceLocator * @return StorageInterface */ public function createService(ServiceLocatorInterface $serviceLocator) { return new CustomRepositoryFactory($serviceLocator); } } 

3) зарегистрируйте фабрику для фабрики хранилища в конфигурации service_manager

 'service_manager' => array( 'factories' => array( 'My\ORM\Repository\CustomRepositoryFactory' => 'My\ORM\Repository\Factory\CustomRepositoryFactoryFactory' ) ) 

4) зарегистрируйте фабрику репозитория в конфигурации доктрины

 'doctrine' => array( 'configuration' => array( 'orm_default' => array( 'repository_factory' => 'My\ORM\Repository\CustomRepositoryFactory' ) ) )