Применение кеширования Doctrine DBAL в Symfony2

В Symfony2 DoctrineBundle отвечает за внедрение и настройку Doctrine, включая DBAL. Но этот бандл пока не поддерживает настройку кеширования DBAL (но поддерживает его для ORM части Doctrine).

Для начала вам потребуется создать CompilerPass внутри своего бандла. Он будет отвечать за выгрузку службы dbal и добавления необходимых настроек для поддержки кеширования.

<?php
// src/Acme/HelloBundle/DependencyInjection/Compiler/AddDbalCacheConfigurationPass.php
namespace Acme\HelloBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
class AddDbalCacheConfigurationPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $id = 'doctrine.dbal.default_connection.configuration';
        if ($container->hasDefinition($id)) {
            $container
                ->getDefinition($id)
                    ->addMethodCall('setResultCacheImpl', array(new Reference('doctrine.orm.default_result_cache')))
            ;
        }
    }
}

Как вы видите в документации Doctrine для того, чтобы настроить DBAL кеширование необходимо вызвать метод setResultCacheImpl объекта настройки dbal, и указать в нем драйвер для кеширования. В нашем случае мы передаем этому методу ссылку на необходимую службу. Саму службу создает DoctrineBundle для ORM кеширования. Трюк заключается в том, что мы используем ту же самую, уже настроенную, службу для упрощения задачи.

Итак, настраиваем кеш драйвер:

// app/config/config.yml
doctrine:
    orm:
        query_cache_driver: apc

Затем передайте CompilerPass вашему ContainerBuilder в главном классе вашего бандла:

<?php
// src/Acme/HelloBundle/AcmeHelloBundle.php
namespace Acme\HelloBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Kreatys\Ie3Bundle\DependencyInjection\Compiler\AddDbalCacheConfigurationPass;
class AcmeHelloBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $container->addCompilerPass(new AddDbalCacheConfigurationPass());
    }
}

Наконец, вам достаточно выполнить запрос при помощи DBAL и применить QueryCacheProfile:

<?php
// src/Acme/HelloBundle/Repository/MyEntityRepository.php
// ...
$lifetime = 1800;
$params = array('myParam' => 'myValue');
$conn = $this->getEntityManager()->getConnection();
$qb = $conn->createQueryBuilder();
$qb
    ->select('name')
    ->from('myTable', 't')
    ->where('something = :myParam')
;
$query = $qb->getSql();
$stmt = $conn->executeQuery($query, $params,     array(\Doctrine\DBAL\Connection::PARAM_STR_ARRAY), new QueryCacheProfile($lifetime, 'my_cache_key'));
$result = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$stmt->closeCursor(); // very important, do not forget
// ...