How to cache doctrine "findOneBy()" query with cache id and cache lifetime option in Symfony 2.4?
You need to redefine every findBy* or findOneBy* function into custom repository: this is the only way as doctrine2 default behaviour doesn't take into account this situation.Is up to you, unfortunately.
Also Ocramius (a Doctrine2 devel) say it here https://groups.google.com/d/msg/doctrine-user/RIeH8ZkKyEY/HnR7h2p0lCQJ
Make a common function for this.
$repo->findOneByYourSufff($yourStuff, $yourRepoClass);
Followed by your common function :
public function findOneByYourSufff($yourStuff, $yourRepoClass) { $q = $this->createQueryBuilder() ->select('x.*') ->from($yourRepoClass, 'x'); foreach($yourStuff as $fieldKey => $wh) { $q->andWhere("b.$fieldKey = :fieldName"); $q->setParameter("fieldName", $wh); } $q->useResultCache(true) ->setResultCacheLifetime(120) //Query Cache lifetime ->setResultCacheId($queryCacheId) //Query Cache Id ->getSingleResult(); return $q }
Here is an example of how you could cache results from a single repository for the functions:
findOneBy(['foo' => 'bar'])
findOneByFoo('bar')
findOneBy(['bar' => 'foo', 'foo' => 'bar')
- etc...
It overrides the EntityRepository::FindOneBy
function. It follows the same signature so there is no need to update the invoking code. All FindOneBy%
type calls will pass through our implementation of findOneBy
.
<?php/*** MyObject Repo */namespace MyLib\Entity\Repository;use Doctrine\ORM\EntityRepository;class MyObjectRepository extends EntityRepository{ const CACHE_KEY = 'my_object'; const ALIAS = 'my_object'; /** * Override - use cache. * * @param array $criteria * @param array|null $orderBy * @return mixed */ public function findOneBy(array $criteria, array $orderBy = null) { $queryBuilder = $this->createQueryBuilder(self::ALIAS); foreach($criteria as $field => $value) { $queryBuilder->andWhere(self::ALIAS . ".{$field} = :{$field}")->setParameter($field, $value); } if (is_array($orderBy)) { foreach ($orderBy as $field => $dir) { $queryBuilder->addOrderBy($field, $dir); } } $queryBuilder->setMaxResults(1); $query = $queryBuilder->getQuery(); $query->useResultCache(true, 3600, self::CACHE_KEY); $result = $query->getResult(); if ($result) return reset($result); return $result; } /** * Depending how you hydrate the entities may make more * sense to use cache layer at findAll * * @param void * @return array The entities. */ public function findAll() { $query = $this->getEntityManager()->createQuery('select v from \OAS\Entity\MyObject v'); $query->useResultCache(true, 3600, self::CACHE_KEY); $result = $query->getResult(); return $result; } /** * */ public function invalidateCache() { //this would depend on your cache implementation... $container = \Zend_Registry::get('doctrine'); $cache = $container->getCacheInstance(); $cache->delete(self::CACHE_KEY); }}
This could be done in a more OOP fashion of course, extending an intermediary class, if you wanted to say have a property on the repository which simply turned the cache on or off. You could extend a similar approach for other repository operations functions.