Create a doctrine repository with dependencies (dependency injection) in ZF2

∥☆過路亽.° 提交于 2019-12-03 04:49:25

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 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) Create a factory for the repository factory

<?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) 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\CustomRepositoryFactory'
        )
    )
)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!