Is there any way to invalidate cached version of a whole-cached page (I use COutputCache as a filter in controller)? I know that I can use subclasses of CCacheDependency, but this solution isn’t perfect: one needs to call the method with all request and it can be complicated if conditions are more complicated.
I didn’t mean “clear the whole cache” but “delete the single page from cache”. Single page = what was cached with COutputCache filter. And I don’t want to do this from console level, but from the class (api) level.
[s]The first thing you need to know, is what ID value is the cache you want to flush (erase). Assuming you know it and you place that value in $pageCacheIDorFragment, hen, just use:
I don’t wont to flush all the cache (cacheID is the ID of WHOLE cache), I want to delete SINGLE page in cache (keyCache instead of cacheID is what I want).
This question comes up from time to time. Yii’s caching mechanism is a little different. Maybe it helps to first understand how the components interact with each other. Instead of talking to the cache like this:
"Hey cache, please delete page xyz…"
The cache will ask you each time, a page is found in the cache:
"Hey, you out there: I have a cached version for the current request here. Is it still valid?"
So, what you want to do instead, is to attach a cache dependency, that will answer this question with no, if a page is expired. Then the cache component will throw it out of the cache automatically.
CExpressionDependency should be the most flexible one.
Let’s say, if you edit a page, that could have been cached, you want this page to get removed from the cache. To do so you first need to think about how you compose a custom unique page key, that identifies a page. This could be “actionId + itemId” or something more complicated. It completely depends on your application. You should be able to compose this key from the request data of any page that should be cached.
Now the basic principle could be like this:
When you edit the page, you use use your custom page key and save a "expired" flag under that key somewhere (maybe also in the cache)
In the dependency you use the same key and check if the expired flag is set. If it is set, you remove that flag and return false.
I have to admit, that i’ve never used a cache dependency, but that’s the way i would try it.
What do you mean with Cache Objects / Fragments here? There’s usually only 1 cache component in the application. If you call flush() on that component, it will erase all content from the cache.
Another, maybe easier way to solve this issue might be, to extend COutputCache and override getCacheKey() there. You could create some static method that generates a key from a set of given parameters. Again you need to come up with a logic how to create a unique cache id for any given page that should get cached.
public function getCacheKey()
{
// Retrieve any request data, that you need to identify the current page here
return self::createCacheKey($param1,$param2,$param3,...);
}
public static function createCacheKey($param1,$param2,$param3,...)
{
// put some logic to compose a unique key from the params here
}
Now, when you want to remove a specific page from the cache, you should know the params, that identify this page (again: depends heaviliy on the different request params of your pages). Then you can remove this page from the cache like this:
Now if you add “?nocache” to a cached page, the cached page will be removed. So far so good - but now a new version was cached with “?nocache”. So if you reload the page with “?nocache” it will show the recently cached page. To flush this page again, you’ll have to load the page again without “?nocache”.