inyeccion ejemplo dependencias php doctrine2 dependency-injection zend-framework2 doctrine

php - ejemplo - Crear un repositorio de doctrina con dependencias(inyección de dependencia) en ZF2



inyeccion de dependencias php (1)

Quiero hacer un repositorio con dependencias duras. Encontré esta publicación en el blog de Jurian Sluisman, pero él sugiere obtener el repositorio del administrador del servicio e inyectarlo en el servicio cuando sea necesario.

Sería mucho mejor si pudiera obtener mis repositorios personalizados con dependencias inyectadas como normalmente desde mi instancia EntityManager o ObjectManager utilizando el método getRepository :

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

¿Cómo puedo usar la inyección de constructor en mis Repositorios y todavía obtenerlos como normalmente desde el ObjectManager directamente con el método getRepository ?


Doctrine utiliza una clase de fábrica Doctrine/ORM/EntityManagerInterface/DefaultRepositoryFactory para crear instancias de repositorio. Si no se establece fábrica personalizada, esta fábrica predeterminada se crea aquí en el método getRepositoryFactory en la clase Doctrine/ORM/Configuration .

Al definir un repository_factory personalizado, podemos sobreescribir esta clase de fábrica predeterminada y agregar lógica personalizada a la fábrica que inyectará las dependencias duras:

Para ilustrar cómo puede hacer esto, mostraré un ejemplo en el que la clase de fábrica de repositorio crea repositorios que dependen de una instancia de ServiceLocator través de la inyección del constructor.

1) hacer una clase de fábrica personalizada que implemente la interfaz doctrina RepositoryFactory

Esta clase se ve muy similar a la doctrina clase 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) Crear una fábrica para la fábrica de repositorios

<?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) registrar la fábrica para la fábrica de repositorios en la configuración service_manager

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

4) registrar la fábrica de repositorios en la configuración de doctrina

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