Reputation: 31
I've just installed Memcached and i'm trying to use it to cache results of various queries done with Doctrine ORM (Doctrine 2.4.8+, Symfony 2.8+).
My app/config/config_prod.yml
have this :
doctrine:
orm:
metadata_cache_driver: memcached
result_cache_driver: memcached
query_cache_driver: memcached
And i tried to useResultCache()
on 2 queries like that (i just replaced the cache id here for the example) : return $query->useResultCache(true, 300, "my_cache_id")->getArrayResult();
. Special queries here because they're native queries (SQL) due to their complexity, but the method is available for any query (class AbstractQuery) so i assume it should work.
Unfortunately, it doesn't. Everytime i refresh the page, if i just did a change in the database, the change is displayed. I've checked the stats of memcached and it seems there're still some cache hits but i don't really know how, cf. what i just said.
Does anyone has an idea on why the cache doesn't seem to be used here to get the supposedly cached results ? Did i misunderstand something and the TTL is ignored somehow ?
There's no error generated, memcached log is empty.
As requested by @nifr, here is the layout of my code to create the 2 native queries i put a Memcached test on :
$rsm = new ResultSetMapping;
$rsm->addEntityResult('my_entity_user', 'u');
// some $rsm->addFieldResult('u', 'column', 'field');
// some $rsm->addScalarResult('column', 'alias');
$sqlQuery = 'SELECT
...
FROM ...
INNER JOIN ... ON ...
INNER JOIN ... ON ...
// some more join
WHERE condition1
AND condition2';
// some conditions added depending on params passed to this function
$sqlQuery .= '
AND (fieldX = (subrequest1))
AND (fieldY = (subrequest2))
AND condition3
AND condition4
GROUP BY ...
ORDER BY ...
LIMIT :nbPerPage
OFFSET :offset
';
$query =
$this->_em->createNativeQuery($sqlQuery, $rsm)
// some ->setParameter('param', value)
;
return $query->useResultCache(true, 300, "my_cache_id")->getArrayResult();
Upvotes: 2
Views: 2316
Reputation: 31
So, it seems for some reason Doctrine doesn't succeed to get the ResultCacheDriver. I tried to set it before the useResultCache()
but i had an exception from Memcached : Error: Call to a member function get() on null
.
I've decided to do it more directly by calling Memcached(). I guess i'll do this kind of stuff in controllers and repositories, depending on my needs. After some tests it works perfectly.
Here is what i basically do :
$cacheHit = false;
$cacheId = md5("my_cache_id"); // Generate an hash for your cache id
// We check if Memcached exists, if it's not installed in dev environment for instance
if (class_exists('Memcached'))
{
$cache = new \Memcached();
$cache->addServer('localhost', 11211);
$cacheContent = $cache->get($cacheId);
// We check if the content is already cached
if ($cacheContent != false)
{
// Content cached, that's a cache hit
$content = $cacheContent;
$cacheHit = true;
}
}
// No cache hit ? We do our stuff and set the cache content for future requests
if ($cacheHit == false)
{
// Do the stuff you want to cache here and put it in a variable, $content for instance
if (class_exists('Memcached') and $cacheHit == false) $cache->set($cacheId, $content, time() + 600); // Here cache will expire in 600 seconds
}
I'll probably put this in a Service. Not sure yet what's the "best practice" for this kind of stuff.
Edit : I did a service. But it only works with native sql... So the problem stays unsolved.
Edit² : I've found a working solution about this null issue (meaning it couldn't find Memcached). The bit of code :
$memcached = new \Memcached();
$memcached->addServer('localhost', 11211);
$doctrineMemcached = new \Doctrine\Common\Cache\MemcachedCache();
$doctrineMemcached->setMemcached($memcached);
$query
->setResultCacheDriver($doctrineMemcached)
->useResultCache(true, 300);
Now, i would like to know which stuff should i put in the config_prod.yml
to just use the useResultCache()
function.
Upvotes: 1