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

前端 未结 1 555
梦谈多话
梦谈多话 2021-02-06 15:22

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 an

相关标签:
1条回答
  • 2021-02-06 16:22

    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'
            )
        )
    )
    
    0 讨论(0)
提交回复
热议问题