Here's just a quick note for those of you working with caching solutions for dynamic data in Symfony.
Update: If testability is a concern, please read the follow up to this article.
One of the challenges with caching is deciding where the limit is. What's worth caching, and what isn't. Because cleaning up that old data is hard... isn't it?
Not so much!
You just need to make a helper and a checks, and you'll be expertly picking out the templates to invalidate!
The first hurdle with clearing out invalid data, is that usually your backend is separate from the frontend, so it's a non-trivial reach to try and invalidate cache files of other applications. Or is it?
<?php
class cacheAssistant
{
public static function clearCachePattern($pattern)
{
$envs = array('prod', 'dev');
$apps = array('backend', 'frontend');
foreach($envs as $env)
{
foreach($apps as $app)
{
$app_cache_dir = sfConfig::get('sf_cache_dir').DIRECTORY_SEPARATOR.$app. DIRECTORY_SEPARATOR.$env.DIRECTORY_SEPARATOR.'template';
$cache_vars = array(
'cache_dir' => $app_cache_dir,
'cache_key_use_vary_headers' => true,
'cache_key_use_host_name' => true,
);
$cache = new sfFileCache($cache_vars);
$cache->removePattern($pattern);
}
}
}
} |
<?php
class cacheAssistant
{
public static function clearCachePattern($pattern)
{
$envs = array('prod', 'dev');
$apps = array('backend', 'frontend');
foreach($envs as $env)
{
foreach($apps as $app)
{
$app_cache_dir = sfConfig::get('sf_cache_dir').DIRECTORY_SEPARATOR.$app. DIRECTORY_SEPARATOR.$env.DIRECTORY_SEPARATOR.'template';
$cache_vars = array(
'cache_dir' => $app_cache_dir,
'cache_key_use_vary_headers' => true,
'cache_key_use_host_name' => true,
);
$cache = new sfFileCache($cache_vars);
$cache->removePattern($pattern);
}
}
}
}
Your $cache_vars will differ depending on your cache settings, but essentially, that's your main helper setup.
Now here's what I use in my objects for cache clear detection:
<?php
class MyObject extends Doctrine_Record
{
private $pendingClearCacheEntries = false;
public function preSave($event)
{
if ($this->isModified())
$this->pendingClearCacheEntries = true;
}
public function postSave($event)
{
if ($this->pendingClearCacheEntries)
{
$this->clearCacheEntries();
$this->pendingClearCacheEntries = false;
}
}
public function clearCacheEntries()
{
cacheAssistant::clearCachePattern('**/**/pages/index');
}
} |
<?php
class MyObject extends Doctrine_Record
{
private $pendingClearCacheEntries = false;
public function preSave($event)
{
if ($this->isModified())
$this->pendingClearCacheEntries = true;
}
public function postSave($event)
{
if ($this->pendingClearCacheEntries)
{
$this->clearCacheEntries();
$this->pendingClearCacheEntries = false;
}
}
public function clearCacheEntries()
{
cacheAssistant::clearCachePattern('**/**/pages/index');
}
}
Of course, your patterns will change depending on your cache options (I.e. I use the / because I have enabled cache_key_use_host_name, other settings may not accept this pattern.)
Happy caching, and if you have any questions, feel free to let me know!