Yii 1.1: flushable

Flush records from the cache with this dependency
14 followers

This dependency can be used to flush an item from the cache. It allows you to invalidate any cached item like a cached ActiveRecord, a DAO query result, a cached fragment or a cached page.

Usage

Import the class file

Either add this line on top of every class file where you want to use it:

Yii::import('ext.flushable.FlushableDependency');

or add ext.flushable.FlushableDependency right to the import section of your main.php configuration file.

How to use the dependency

When you create the dependency you have to provide a unique $id wich identifies your cached content.

$dependency = new FlushableDependency('myKey');

Now you can use it for data, fragment or page caching.

If you want to cache some ActiveRecord or DAO result the $id is usually the primary key. In this case you should add the model name to avoid conflicts among different cached model classes:

// Cache a ActiveRecord
$dependency = new FlushableDependency($id,'Post');
$post = Post::model()->cache(3600,$dependency)->findByPk($id);

How to flush a content from cache

Whenever you want to invalidate the cached data you can now call:

FlushableDependency::flushItem('myKey');

If you used the dependency for data caching and added a model name you must provide the same name again:

FlushableDependency::flushItem($id,'Post');

You could put this into the afterSave() method of your active record (change $id to $this->id) or just call it manually whenever you update the record.

You can also add an $expire parameter to the flushItem() call. It will specify how long the information about the change should be kept in the cache. So obviously this should be more than the longest time which you cache your content. The default is 3600.

How it works

Whenever an item is cached with this dependency it scans the cache for another key. This key is unique per cached item and composed from the two parameters you pass along to the constructor. This other cache value basically indicates "The item has expired!". So if no such key is found, the item in the cache is still valid.

With a call to flushItem() you will create such an expiration entry in the cache for the cached item. So when the dependency is evaluated the next time it will find something now and the cached content will no longer be seen as valid.

Related forum topic

Changelog

Release 1.1.1

  • Changed dependency value from time() to microtime() to fix timing issues in some scenarios

Release 1.1.0

  • Refactored class interface

Release 1.0.1

  • Initial release

Total 7 comments

#9494 report it
Mike at 2012/08/17 04:02am
Re: Looks great, but...

The underlying cache component is responsible for this. It must make sure that the delete operation works cleanly even if there are multiple servers configured.

#9412 report it
Cstdenis at 2012/08/09 07:44am
Looks great, but...

Looks like a great ext, but I think this will break badly in the case of multiple cache servers.

Needs to be a way to force it to store and check it's dependency information in a specific cache server, and that needs to be configurable at the application level. Should be a simple enough change to make.

#8307 report it
Mike at 2012/05/24 09:43am
Re: Function arguments

@Bethrezen I only had cached DB records in mind when i planned this dependency. But actually you're right - it could be used for everything. Still i find the separation of modelname / id useful.

As the extension is still very fresh, i think it's still ok to change the interface. It will look like this:

public function __constructor($id, $type=null);
public function flushItem($id, $type=null);

So if you don't have a model (=$type) then just leave it away.

#8306 report it
Bethrezen at 2012/05/24 09:23am
Re[2]: Function arguments

@mikl this dependency can be used for many different cache cases, for example fragment caching. Therefore variable name "$model" is not good for understanding the logic of dependency by non-author programmer. If you want to make $model to be an ActiveRecord instance - imo it'll be better to extend the base class of your extension for this purpose.

#8304 report it
Mike at 2012/05/24 06:35am
Re: Function arguments

@Bethrezen It's just for convenience so that you don't have to think about how to create a unique key. Newbies may not know, that they need both to create a unique key.

Maybe in a future version i even make the $id optional and allow $model to be an ActiveRecord instance.

#8303 report it
Bethrezen at 2012/05/24 06:23am
Function arguments

What's the purpose of both $model and $id arguments, while they all only used for cache key? I think it's better to make only one variable - $key.

#8301 report it
Haensel at 2012/05/24 04:21am
Perfect timing!

This is great, thanks! I always wondered why there isn't something like that in the core as it is a quite common use case I think.

Leave a comment

Please to leave your comment.

Create extension