Com o lançamento da versão 2.5 do Doctrine, uma feature há muito esperada tornou-se estável o suficiente para uso. Trata-se do “Second Level Cache”, que segundo a documentação oficial foi projetada para reduzir a quantia de acessos a base de dados. Ele fica entre a aplicação e a base de dados para evitar o maior número possível de acessos ao banco.
Quando habilitado, todas as entidades são primeiro pesquisadas no cache e, caso não sejam encontradas, são realizadas consultas e o valor delas fica em cache, para reduzir o acesso ao banco de dados nas próximas requisições.
O primeiro passo para usar o second level cache é ter certeza de que estamos usando a versão 2.5 ou superior do Doctrine. Para isso, alteramos nosso composer.json para algo parecido com:
{ "require": { "doctrine/common": "2.5.*", "doctrine/dbal": "2.5.*", "doctrine/orm": "2.5.*" } }
Lembre-se de executar o composer update para atualizar o vendor do projeto.
Agora podemos habilitar o cache no bootstrap do projeto na criação do EntityManager.
// Enable second-level-cache //pode ser qualquer outra forma de cache como Memcached, Xcache, etc $cache = new \Doctrine\Common\Cache\ApcCache; $cacheRegionConfiguration = new \Doctrine\ORM\Cache\RegionsConfiguration(); $factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($cacheRegionConfiguration, $cache); $config->setSecondLevelCacheEnabled(); $config->getSecondLevelCacheConfiguration()->setCacheFactory($factory);
O código completo pode ser visto nesse gist.
O próximo passo é configurar nossas entidades para que elas façam uso do cache. Podemos escolher um dos modos de cache disponíveis:
- READ_ONLY, o valor padrão. Permite que as entidades em cache sejam apenas lidas e não modificadas. É a forma mais performática, mas é útil apenas para entidades que são apenas para leitura.
- NONSTRICT_READ_WRITE. Permite que as entidades possam ser alteradas, mas não possui controle de “lock”.
- READ_WRITE. O modo mais completo, permite alterações e faz um controle mais seguro do acesso às entidades evitando conflitos. Mas para isso perde um pouco da performance, e o sistema de cache selecionado precisa permitir o recurso de locks.
Você agora pode configurar cada uma das suas entidades para usar o melhor modo de cache, como no trecho abaixo:
<?php namespace DoctrineNaPratica\Model; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\ArrayCollection; /** * @ORM\Entity * @ORM\Table(name="User") * @ORM\Cache(usage="NONSTRICT_READ_WRITE") */ class User {
Nesse exemplo, foi escolhido o modo NONSTRICT_READ_WRITE, e o cache vai permitir que as entidades sejam alteradas normalmente. Quando uma alteração é realizada, a entidade é persistida do banco de dados e também alterada automaticamente no cache, de forma que as próximas requisições possam acessá-la sem a realização de uma nova consulta no banco de dados.
Na imagem abaixo, é possível ver o cache funcionando no painel do Z-Ray.
Na documentação do Doctrine, é possível ver outras funcionalidades como adicionar um log, alterar o tempo de vida do cache ou mesmo realizar a limpeza dele.
Realmente é uma funcionalidade que permite aumentar muito a performance de projetos usando esse ORM.
P.S.: Este artigo é uma continuação do capítulo sobre performance do livro Doctrine na prática, que pode ser adquirido no Leanpub.