在ZF2中创建依赖关系(依赖注入)的教义存储库 [英] Create a doctrine repository with dependencies (dependency injection) in ZF2
问题描述
如果我能够获得我通过使用 getRepository从我的
方法: EntityManager
或 ObjectManager
实例中注入的依赖关系的自定义存储库
$ objectManager-> getRepository('My\Entity\Class' ;
如何在我的存储库中使用构造函数注入,并从 ObjectManager
直接使用 getRepository
方法
原则使用工厂课程 Doctrine\ORM\EntityManagerInterface\DefaultRepositoryFactory
用于创建存储库实例。如果没有自定义工厂设置,则会创建此默认工厂在 getRepositoryFactory 方法中Configuration.phprel =noreferrer> Doctrine\ORM\Configuration
class 。
通过定义一个自定义的 repository_factory
,我们可以覆盖这个默认的工厂类,并将自定义逻辑添加到工厂,这将注入硬依赖:
为了说明如何执行此操作,我将展示一个示例,其中存储库工厂类通过构造函数注入创建依赖于 ServiceLocator
实例的存储库。 / p>
1)制作一个自定义工厂类来实现原则 RepositoryFactory
interface
这个类loo ks非常类似于教义 DefaultRepositoryFactory
类。
<?php
命名空间My\ORM\Repository;
使用Doctrine\Common\Persistence\ObjectRepository;
使用Doctrine\ORM\Repository\RepositoryFactory;
使用Doctrine\ORM\EntityManagerInterface;
使用Zend\ServiceManager\ServiceLocatorAwareInterface;
使用Zend\ServiceManager\ServiceLocatorAwareTrait;
使用Zend\ServiceManager\ServiceLocatorInterface;
class DefaultRepositoryFactory实现RepositoryFactory,ServiceLocatorAwareInterface
{
使用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 EntityManager实例。
* @param string $ entityName实体的名称。
* @return ObjectRepository
* /
私有函数createRepository(EntityManagerInterface $ entityManager,$ entityName)
{
/ * @var $ metadata \Doctrine\ORM \Mapping\ClassMetadata * /
$ metadata = $ entityManager-> getClassMetadata($ entityName);
$ repositoryClassName = $ metadata-> customRepositoryClassName
?:$ entityManager-> getConfiguration() - > getDefaultRepositoryClassName();
//构造函数注入,我检查子类,但它只是一个例子
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
命名空间My\ORM\Repository\Factory;
使用My\ORM\Repository\DefaultRepositoryFactory;
使用Zend\Cache\Storage\StorageInterface;
使用Zend\ServiceManager\FactoryInterface;
使用Zend\ServiceManager\ServiceLocatorInterface;
class DefaultRepositoryFactoryFactory实现FactoryInterface
{
/ **
* @param ServiceLocatorInterface $ serviceLocator
* @return StorageInterface
* /
public function createService(ServiceLocatorInterface $ serviceLocator)
{
返回新的DefaultRepositoryFactory($ serviceLocator);
}
}
3)为仓库注册工厂在 service_manager中的工厂
配置
'service_manager'= > array(
'factoryories'=> array(
'My\ORM\Repository\CustomRepositoryFactory'=>'My\ORM\Repository\Factory\CustomRepositoryFactoryFactory'
)
)
4)在doctrine配置中注册存储库工厂
'doctrine'=> array(
'configuration'=> array(
'orm_default'=> array(
'repository_factory'=>'My\ORM\Repository\DefaultRepositoryFactory'
)
)
)
I want to make a repository with hard dependencies. I found this blog post by Jurian Sluisman but he suggests getting the repository from the service manager and injecting it into the service where needed.
It would be much better if I would be able to get my custom repositories with injected dependencies like normally from my EntityManager
or ObjectManager
instance by using the getRepository
method:
$objectManager->getRepository('My\Entity\Class');
How can I use constructor injection in my Repositories and still get them like normally from the ObjectManager
directly with the getRepository
method?
Doctrine uses a factory class Doctrine\ORM\EntityManagerInterface\DefaultRepositoryFactory
for creating repository instances. If no custom factory is set this default factory is created here in the getRepositoryFactory
method in the Doctrine\ORM\Configuration
class.
By defining a custom repository_factory
we can overwrite this default factory class and add custom logic to the factory that will inject the hard dependencies:
To illustrate how you can do this I will show an example where the repository factory class creates repositories that are dependent on a ServiceLocator
instance through constructor injection.
1) make a custom factory class that implements the doctrine RepositoryFactory
interface
This class looks very similar to the doctrine DefaultRepositoryFactory
class.
<?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 DefaultRepositoryFactory 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) Create a factory for the repository factory
<?php
namespace My\ORM\Repository\Factory;
use My\ORM\Repository\DefaultRepositoryFactory;
use Zend\Cache\Storage\StorageInterface;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class DefaultRepositoryFactoryFactory implements FactoryInterface
{
/**
* @param ServiceLocatorInterface $serviceLocator
* @return StorageInterface
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
return new DefaultRepositoryFactory($serviceLocator);
}
}
3) register the factory for the repository factory in the service_manager
config
'service_manager' => array(
'factories' => array(
'My\ORM\Repository\CustomRepositoryFactory' => 'My\ORM\Repository\Factory\CustomRepositoryFactoryFactory'
)
)
4) register the repository factory in the doctrine config
'doctrine' => array(
'configuration' => array(
'orm_default' => array(
'repository_factory' => 'My\ORM\Repository\DefaultRepositoryFactory'
)
)
)
这篇关于在ZF2中创建依赖关系(依赖注入)的教义存储库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!