Injecting the Service Manager to Build a Doctrine Repository in ZF2

前端 未结 2 807
不知归路
不知归路 2021-02-11 10:33

How do I inject the service manager into a Doctrine repository to allow me to retrieve the Doctrine Entity Manager?

I using the ZF2-Commons DoctrineORMModule and are try

2条回答
  •  猫巷女王i
    2021-02-11 11:42

    The way i approach things is this:

    First i register a Service for each entity. This is done inside Module.php

    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'my-service-entityname' => 'My\Factory\EntitynameServiceFactory',
            )
        );
    }
    

    Next thing would be to create the factory class src\My\Factory\EntitynameServiceFactory.php. This is the part where you inject the EntityManager into your Entity-Services (not into the entity itself, the entity doesn't need this dependency at all)

    This class looks something like this:

    setEntityManager($serviceLocator->get('Doctrine\ORM\EntityManager'));
            return $service;
        }
    }
    

    Next thing in line is to create the src\My\Service\EntitynameService.php. And this is actually the part where you create all the getter functions and stuff. Personally i extend these Services from a global DoctrineEntityService i will first give you the code for the EntitynameService now. All this does is to actually get the correct repository!

    entityRepository) {
                $this->setEntityRepository($this->getEntityManager()->getRepository('My\Entity\Entityname'));
            }
            return $this->entityRepository;
        }
    }
    

    This part until here should be quite easy to understand (i hope), but that's not all too interesting yet. The magic is happening at the global DoctrineEntityService. And this is the code for that!

    getEventManager()->trigger(__FUNCTION__ . '.pre', $this, array('entities' => $entities));
            $entities = $this->getEntityRepository()->findAll();
            $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array('entities' => $entities));
            return $entities;
        }
    
        public function find($id) {
            return $this->getEntityRepository()->find($id);
        }
    
        public function findByQuery(\Closure $query)
        {
            $queryBuilder = $this->getEntityRepository()->createQueryBuilder('entity');
            $currentQuery = call_user_func($query, $queryBuilder);
           // \Zend\Debug\Debug::dump($currentQuery->getQuery());
            return $currentQuery->getQuery()->getResult();
        }
    
        /**
         * Persists and Entity into the Repository
         *
         * @param Entity $entity
         * @return Entity
         */
        public function persist($entity)
        {
            $this->getEventManager()->trigger(__FUNCTION__ . '.pre', $this, array('entity'=>$entity));
            $this->getEntityManager()->persist($entity);
            $this->getEntityManager()->flush();
            $this->getEventManager()->trigger(__FUNCTION__ . '.post', $this, array('entity'=>$entity));
    
            return $entity;
        }
    
        /**
         * @param \Doctrine\ORM\EntityRepository $entityRepository
         * @return \Haushaltportal\Service\DoctrineEntityService
         */
        public function setEntityRepository(EntityRepository $entityRepository)
        {
            $this->entityRepository = $entityRepository;
            return $this;
        }
    
        /**
         * @param EntityManager $entityManager
         * @return \Haushaltportal\Service\DoctrineEntityService
         */
        public function setEntityManager(EntityManager $entityManager)
        {
            $this->entityManager = $entityManager;
            return $this;
        }
    
        /**
         * @return EntityManager
         */
        public function getEntityManager()
        {
            return $this->entityManager;
        }
    
        /**
         * Inject an EventManager instance
         *
         * @param  EventManagerInterface $eventManager
         * @return \Haushaltportal\Service\DoctrineEntityService
         */
        public function setEventManager(EventManagerInterface $eventManager)
        {
            $this->eventManager = $eventManager;
            return $this;
        }
    
        /**
         * Retrieve the event manager
         * Lazy-loads an EventManager instance if none registered.
         *
         * @return EventManagerInterface
         */
        public function getEventManager()
        {
            return $this->eventManager;
        }
    
        /**
         * Set service manager
         *
         * @param ServiceManager $serviceManager
         * @return \Haushaltportal\Service\DoctrineEntityService
         */
        public function setServiceManager(ServiceManager $serviceManager)
        {
            $this->serviceManager = $serviceManager;
            return $this;
        }
    
        /**
         * Get service manager
         *
         * @return ServiceManager
         */
        public function getServiceManager()
        {
            return $this->serviceManager;
        }
    }
    

    So what does this do? This DoctrineEntityService pretty much is all what you globally need (to my current experience). It has the fincAll(), find($id) and the findByQuery($closure)

    Your next question (hopefully) would only be "How to use this from my controller now?". It's as simple as to call your Service, that you have set up in the first step! Assume this code in your Controllers

    public function someAction()
    {
        /** @var $entityService \my\Service\EntitynameService */
        $entityService = $this->getServiceLocator()->get('my-service-entityname');
    
        // A query that finds all stuff
        $allEntities = $entityService->findAll();
    
        // A query that finds an ID 
        $idEntity = $entityService->find(1);
    
        // A query that finds entities based on a Query
        $queryEntity = $entityService->findByQuery(function($queryBuilder){
            /** @var $queryBuilder\Doctrine\DBAL\Query\QueryBuilder */
            return $queryBuilder->orderBy('entity.somekey', 'ASC'); 
        });
    }
    

    The function findByQuery() would expect an closure. The $queryBuilder (or however you want to name that variable, you can choose) will be an instance of \Doctrine\DBAL\Query\QueryBuilder. This will always be tied to ONE Repository though! Therefore entity.somekey the entity. will be whatever repository you are currently working with.

    If you need access to the EntityManager you'd either only instantiate only the DoctrineEntityService or call the $entityService->getEntityManager() and continue from there.

    I don't know if this approach is overly complex or something. When setting up a new Entity/EntityRepository, all you need to do is to add a new Factory and a new Service. Both of those are pretty much copy paste with two line change of code in each class.

    I hope this has answered your question and given you some insight of how work with ZF2 can be organized.

提交回复
热议问题