私が物事にアプローチする方法は次のとおりです。
まず、エンティティごとにサービスを登録します。これはModule.php内で行われます
public function getServiceConfig()
{
return array(
'factories' => array(
'my-service-entityname' => 'My\Factory\EntitynameServiceFactory',
)
);
}
次に、ファクトリ クラスsrc\My\Factory\EntitynameServiceFactory.phpを作成します。これは、EntityManager を Entity-Services に注入する部分です (エンティティ自体ではなく、エンティティはこの依存関係をまったく必要としません)。
このクラスは次のようになります。
<?php
namespace My\Factory;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;
use My\Service\EntitynameService;
class EntitynameServiceFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$service = new EntitynameService();
$service->setEntityManager($serviceLocator->get('Doctrine\ORM\EntityManager'));
return $service;
}
}
次に、src\My\Service\EntitynameService.phpを作成します。そして、これは実際には、すべての getter 関数などを作成する部分です。個人的には、これらのサービスをグローバルDoctrineEntityServiceから拡張します。最初にEntitynameServiceのコードを提供します。これが行うことは、実際に正しいリポジトリを取得することだけです!
<?php
namespace My\Service;
class EntitynameService extends DoctrineEntityService
{
public function getEntityRepository()
{
if (null === $this->entityRepository) {
$this->setEntityRepository($this->getEntityManager()->getRepository('My\Entity\Entityname'));
}
return $this->entityRepository;
}
}
ここまではかなり理解しやすいはずですが(願わくば)、まだそれほど興味深いものではありません。グローバルなDoctrineEntityServiceで魔法が起こっています。そして、これがそのコードです!
<?php
namespace My\Service;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManagerInterface;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\ServiceManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
class DoctrineEntityService implements
ServiceManagerAwareInterface,
EventManagerAwareInterface
{
protected $serviceManager;
protected $eventManager;
protected $entityManager;
protected $entityRepository;
/**
* Returns all Entities
*
* @return EntityRepository
*/
public function findAll()
{
$this->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;
}
}
それで、これは何をしますか?このDoctrineEntityServiceは、(私の現在の経験では) グローバルに必要なもののほとんどすべてです。fincAll()
、find($id)
および_findByQuery($closure)
あなたの次の質問は (願わくば) 「今、コントローラーからこれを使用する方法は?」 だけです。最初のステップで設定した Service を呼び出すのと同じくらい簡単です。コントローラーでこのコードを想定します
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');
});
}
関数findByQuery()
はクロージャを期待します。($queryBuilder
または、その変数に名前を付ける方法を選択できます)は、のインスタンスになります\Doctrine\DBAL\Query\QueryBuilder
。これは常に関連付けられONE Repository
ますが!したがってentity.somekey
、entity.
は現在使用しているリポジトリになります。
へのアクセスが必要な場合EntityManager
は、 のみをインスタンス化するDoctrineEntityService
か、 を呼び出して$entityService->getEntityManager()
そこから続行します。
このアプローチが過度に複雑かどうかはわかりません。新しい Entity/EntityRepository を設定するときは、新しい Factory と新しい Service を追加するだけです。これらは両方とも、各クラスのコードを 2 行変更したコピー ペーストです。
これがあなたの質問に答え、ZF2 での作業をどのように整理するかについての洞察を与えてくれたことを願っています。