Schneimi’s Dev Weblog


User specific caching in CakePHP

Posted in CakePHP by schneimi on February 2, 2013
Tags: , ,

CakePHP caching depends all on controllers and given arguments. But, what if you want different cache files for conditions that don’t come along with the arguments, like session variables?

In my case, I simply wanted separate cache files for each user of my app, because some actions deliver different views for different users, and I didn’t want to pass the User.id to each action in every controller that was concerned.

So I had a look into the CacheHelper and noticed that the file name for cache files is just build from the controller name and given arguments. First I tried to make a modified version of CacheHelper for my app. I don’t remember what problems I ran into, but it just didn’t work out very well.

Then I came up with the idea to internally manipulate the URL, just before the cache is read and written. Somehow this lead me to the lib/Cake/Routing/Filter/CacheDispatcher.php, where I needed just a few lines of additional code to put the User.id into place, which worked like a charm and had no side effects.

You have to copy the original lib/Cake/Routing/Filter/CacheDispatcher.php into your app app/Routing/Filter/UserCacheDispatcher.php and add the following lines of code. To put the dispatcher into action you finally have to register it in the bootstrap.php and replace the core CacheDispatcher.


app/Routing/Filter/UserCacheDispatcher.php

(...)
public function beforeDispatch($event) {
    // load SessionComponent
    App::uses('SessionComponent', 'Controller/Component');
    $session = new SessionComponent(new ComponentCollection());
    $userID = $session->read('User.userID');

    if (!empty($userID)) {
      // add user id to request url with 'u' prefix
      $event->data['request']->here = $event->data['request']->here.'/u'.$userID;

      // remove request parameters to solve issue with ajax request random number parameter
      $event->data['request']->query = '';
    } else {
      return;
    }
(...)


app/Config/bootstrap.php

Configure::write('Dispatcher.filters', array(
    'AssetDispatcher',
    'UserCacheDispatcher'
));

I wonder why this use case is not supported by CakePHP out of the box, or didn’t I just see it? Well, I am aware that this might not be the best solution, but it is at least a pretty simple and effective workaround. Any ideas on how to solve the problem in better ways are welcome.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: