EntityRepositoryからContainerを参照したかったので作ってみました。
標準ではEntityRepository内からContainerを参照したい場合
global $kernel;
if ($kernel instanceOf \AppCache) {
$kernel = $kernel->getKernel();
}
$container = $kernel->getContainer();
と記述する必要がありますが、
$container = $this->getContainer();
と記述するだけでContainerを参照できるようになります。
環境
- Symfony 2.3.17
- Doctrine 2.4.4
- DoctrineBundle 1.2.0
実装する
実装手順は下記の通りです。
1. Containerを参照可能なEntityRepositoryクラス(ContainerAwareEntityRepository)を作成
ContainerAwareEntityRepository.php
<?php
namespace Some\MyBundle\Doctrine\ORM;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ContainerAwareEntityRepository extends EntityRepository implements ContainerAwareInterface
{
/**
* Container
* @var ContainerInterface
*/
private $container;
/**
* {@inheritdoc}
*/
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
/**
* Get Container
* @return ContainerInterface
*/
public function getContainer()
{
return $this->container;
}
}
2. ContainerAwareEntityRepositoryにContainerを設定するRepositoryFactoryクラス(MyRepositoryFactory)を作成
MyRepositoryFactory.php
<?php
namespace Some\MyBundle\Doctrine\ORM\Repository;
use Some\MyBundle\Doctrine\ORM\ContainerAwareEntityRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Repository\DefaultRepositoryFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
class MyRepositoryFactory extends DefaultRepositoryFactory
{
/**
* Container
* @var ContainerInterface
*/
private $container;
/**
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* {@inheritdoc}
*/
public function getRepository(EntityManagerInterface $entityManager, $entityName)
{
$repository = parent::getRepository($entityManager, $entityName);
if ($repository instanceof ContainerAwareEntityRepository) {
$repository->setContainer($this->container);
}
return $repository;
}
}
サービスへの登録も忘れずに行います。
services.yml
services:
my.doctrine.orm.repository_factory:
class: Some\MyBundle\Doctrine\ORM\Repository\MyRepositoryFactory
arguments: [ @service_container ]
3. MyRepositoryFactoryをEntityManagerに登録するCompilerPassクラス(MyCompilerPass)を作成
CompilerPassは他のBundleで定義されたサービスを操作する場合に利用します。
今回はDoctrineBundleで定義されたサービスに対して操作を行う必要があるので作成します。
MyCompilerPass.php
<?php
namespace Some\MyBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class MyCompilerPass implements CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
$repositoryFactory = $container->getDefinition('my.doctrine.orm.repository_factory');
$container->findDefinition('doctrine.orm.configuration')->addMethodCall('setRepositoryFactory', [$repositoryFactory]);
}
}
4. MyCompilerPassをContainerBuilderに登録する
SomeMyBundle.php
<?php
namespace Some\MyBundle;
use Some\MyBundle\DependencyInjection\Compiler\MyCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class SomeMyBundle extends Bundle
{
/**
* {@inheritdoc}
*/
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new MyCompilerPass());
}
}
使用する
ContainerAwareEntityRepositoryを継承したクラス内で$this->getContainer()
するとContainerを参照できます。
SomeTableRepository.php
<?php
namespace Some\MyBundle\Entity\SomeTableRepository;
use Some\MyBundle\Doctrine\ORM\ContainerAwareEntityRepository;
/**
* SomeTableRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class SomeTableRepository extends ContainerAwareEntityRepository
{
/**
* Get Some Data
* @param int $id
* @return SomeTable
*/
public function get($id)
{
$container = $this->getContainer();
$someParam = $container->getParameter('some.parameter');
$qb = $this
->createQueryBuilder('some')
->where('some.id = :id')
->andWhere('some.someColumn = :someParam')
->setParameters([
'id' => $id,
'someParam' => $someParam,
])
;
$logger = $container->get('logger');
$logger->debug("Repositoryからログ出力!");
return $qb->getQuery()->getSingleResult();
}
}