在ZF2中创建依赖关系(依赖注入)的教义存储库 [英] Create a doctrine repository with dependencies (dependency injection) in ZF2

查看:171
本文介绍了在ZF2中创建依赖关系(依赖注入)的教义存储库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用硬依赖的存储库。我发现 这个由Jurian Sluisman发表的博客 ,但是他建议从服务管理器获取存储库,并在需要时将其注入到服务中。



如果我能够获得我通过使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆