Hello, this article will describe some aspects about caching controllers with filters() method in your controller. And I will describe some problems I meet when using this approach for caching, the main problem was
how can i invalidate a cache for specific action? ¶
I googled the forum
- how to delete whole-page cache from cache?
- flush controller cache
- Is there any way to invalidate cached version of a whole-cached page?
asked on IRC and SO but I didn't find an answer, therefore decided to write this article.
Our first task is to invalidate a cache for specific page. When you use filters() and COutputCache in your controller you will find some restrictions of this approach.
- If you change your filters() caching settings, you need to invalidate your cached data, before your filters() changes will be in action.
- You can't invalidate a specific page or specific action, and sometimes you don't need and don't want to flush whole cache, for example: if you're changing your duration option.
- If you change some dependency in your filters() you also don't need and don't want flush whole cache.
Yii doesn't have an implemented function for this and i need to make it. At first we need to create our own Cache Component.
Note: I will use CFileCache component, because i use CFileCache as my main cache. But it should work with every cache class.
I created MyCache.php file in ./protected/components/
class MyCache extends CFileCache
{
public function getValue($key) {
if( isset( $_GET['flush'] ) )
$this->deleteValue($key);
return parent::getValue($key);
}
}
Next step, you need to change your cache class in your config.
'cache'=>array(
//'class'=>'system.caching.CFileCache',
'class'=>'MyCache',
),
That's all. Now when you want to invalidate a specific page cache, you just need to add a flush variable into your URI request. ex: To invalidate just index page from the cache, use this url: www.myyiisite.com/?flush . That's all, index page is invalidated and new cache settings is now in action.
Drowbacks:
- I can't invalidate a controller cache. If you have 10 controllers in your app, and change your filters() code, you don't want to flush whole cache. You want to invalidate the cache just for this controller. And Yii can't.
This is a good idea, but…
you should not implement it this way.
First, if you want to change the cache system your app is using (in your case, CFileCahce), the only thing you need to do is change your main configuration file. You can even let the administrator decide which cache to use. But now you'll have to dig into the code and change the base class for your MyCache.
Second, this is a violation of the single responsibility principle. CCache and it's descendants provide the caching functionality; it's not their business to access $_GET or even know that $_GET exists.
Instead you should use create a custom filter or an application-wide onBeginRequest event handler — a function which will be executed before COutputCache filter kicks in.
Still, the core idea is good. I think I'll implement it in my app. :)
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.