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();
    }
}