Cache Questions

Hello!

I have some questions about Caching in Yii. I would like to know is there any way to invalidate a particular Fragment Cache (COutputCache)? I have created it in a view file but I would like to invalidate it at the moment of adding a new comment, for example, and to do it in the Comments Model with overriding the parent save() method with just adding the cache cleaning for the particular key?

Thanks in advance.

There is no automatic solution but you could build a simple system with dependencies. The problem is, that Yii can not know, what parameter identifies for example a comment. You need to add some custom code here. The logic could be like this:

  1. If a comment is updated, set a flag in the cache, e.g. with key name "commentExpired_346", where 346 is the Primary key.

  2. Use a cache dependency at the place where you use the fragment cache. You should know the Comment id there. So it’s easy to compose the key name above.

The code for both code look like this:




// ... Comment was updated, now set a flag:

Yii::app()->cache->set('commentExpired_'.$comment_id);

You could use a CExpressionDependency. You also should make sure, that you delete the expire flag afterwards. Something like this should work:




$key='commentExpired_'.$comment_id;

$this->beginCache('comment',array(

    'dependency'=>array(

        'class'=>'CExpressionDependency',

        'expression'=>"Yii::app()->cache->get('$key') && Yii::app()->cache->delete('$key')",

    ),

));

Note that i didn’t test the above code. So you may have to tune it a little. But i think, the main logic should work.

Thank you very much. With some slight changes the code works perfectly :)

Cool. Would you let me know, what didn’t work? I will update the posting for future reference…

Sure, I will. Just need a couple of days because I have some rush here with other stuff :)

Hi, sorry for the delay.

My code follows the following logic. In the view where I use the partial Cache I use the following condition




$key = Yii::app()->name . ".ProjectListing.RecentComments";

if($this->beginCache($key, array('dependency' => array(

                                     'class' => 'CExpressionDependency',

                                     'expression' => "Yii::app()->cache->get('$key')",

                    ),

))) {

    Yii::app()->cache->delete($key);

    $this->beginWidget('zii.widgets.CPortlet', array(

    	'title' => 'Recent Comments',

    ));


    $this->widget('RecentComments');

    $this->endWidget();

    $this->endCache();

}



then if there is the the said cache this means we have altered the widget content and we need to refresh the partial cache. The $key represents a simple true/false cache which is created in the model when the recent comments are altered. If this cache exists we enter the widget, query the database and delete this cache.

I hope I explained well enough :)

If any questions I am happy to answer, if something is not clear :)

Mike,

This is a very good, although short reading. Would you consider writing a Cookbook recipe on this?

I will consider it, when i find some more time.