How to cache doctrine "findOneBy()" query with cache id and cache lifetime option in Symfony 2.4? How to cache doctrine "findOneBy()" query with cache id and cache lifetime option in Symfony 2.4? symfony symfony

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.