ecache - easy per user or per anything cache of html or arrays

By alan blount aka "zeroasterisk"
Caching is basically required for any data-heavy or interaction-heavy site... but you need to be in control of who gets what cache; more specifically, you need to be sure people only get their own cached content.
Cake < 1.2 has caching... great caching if your contact is the same for everyone... but it's less than ideal for per-user content... in fact if you wanted to cache the "public" version of a view, and ignore cache >userid; and even for one site an additional parameter: $this->repid. The cache file name defaults to starting with the current controller_action... but they can be arbitrarily set (which is how I use it most of the time).

Feel free to add other parameters, if you need to split your caches by other things... for me, I just needed a unique cache per userid and per repid.

Controller Class:

Download code <?php 
/***
* == Example of Usage ==
* The following is simply an example of how you might use the component.
*/
class MockUserController extends AppController {
    var 
$components = array('Ecache');
    
    
/** 
    * This component doesn't handle authentication, nor does it automatically integrate with any other authenticaiton system.
    * You have to tell it what userid is logged in.  
    * This shouldn't be too difficult, as most authenticaiton systems will have unique user ids.
    * If you don't have an authentication system, you probably don't need this component, as all you're cached data will look the same for all people.
    */
    
function beforeFilter() {
        
// whatever your authentication sets
        
$this->userid $this->myAuthenticaitonSystem();
        
        
// populating value with a number, so we can discuss in this example.
        
$this->userid 42// mockup value!
        
        // initialize Ecache
        
$this->Ecache->startup($this);
    }
    
    
/**
    * simple ecache example.  just a regular database data result cached.
    * cache filename will be: ./app/tmp/cache/views/users_list_0_42_0.php
    * if $this->userid was 89, the cache filename would be: ./app/tmp/cache/views/users_list_0_89_0.php
    */
    
function example1() {
        
// checking cache
        
$d $this->Ecache->ecache(null,'users','list');
        
// if missing cached content
        
if (empty($d)) {
            
// now get cached content
            
$cond = array('User.parent_id'=>$this->userid);
            
$results $this->User->findAll($cond);
            
// writing cache
            
$d $this->Ecache->ecache($results,'users','list');
        }
        
$this->set('myusers',$d);
    }

    
/** 
    * there are 2 differnt cache calls in this example.
    * the first is like above, based on the $this->userid.
    * cache filename will be: ./app/tmp/cache/views/users_pageelement_0_42_0.php
    * if $this->userid was 89, the cache filename would be: ./app/tmp/cache/views/users_pageelement_0_89_0.php
    * the second will cache content globally (not on a per-user basis)
    * cache filename will be: ./app/tmp/cache/views/users_pageelement_0_global_global.php
    * notice that the content in this example is generated from returned "requestAction"s
    */
    
function example2() {
        
// checking cache
        
$d $this->Ecache->ecache(null,'users','pageelement');
        
// if missing cached content
        
if (empty($d)) {
            
// now get cached content
            
$results $this->requestAction('/something/action',array('return'));
            
// writing cache
            
$d $this->Ecache->ecache($results,'users','pageelement');
        }
        
$this->set('user_specific_content',$d);

        
// checking cache
        
$d $this->Ecache->ecache(null,'users','pageelement',0,'global','global');
        
// if missing cached content
        
if (empty($d)) {
            
// now get cached content
            
$results $this->requestAction('/anything/content',array('return'));
            
// writing cache
            
$d $this->Ecache->ecache($results,'users','pageelement',0,'global','global');
        }
        
$this->set('global_content',$d);
    }
    
    
/** 
    * This is simply a convenience wrapper for clearing the cache files.
    * clearing cache deletes: ./app/tmp/cache/view/*
    * ...often you may need to clear from a model, afterSave()
    */
    
function exampleClear() {
        
$this->Ecache->clear();
    }
}
?>


Obviously, the above examples were simple. If you had a huge database query it might be worth it to cache, or if you used the same content a lot... most of the time though, caching is really useful for multiple database operations, heavily processed data, or returned "requestAction" data.

Component Class:

Download code <?php 
/***
 * PHP versions 4 and 5
 *
 * ecache: extends and simplifies caching content based on per-user or per--anything parameters for the cakePHP framework.
 * Copyright (c)    2007, Alan Blount
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @author           Alan Blount
 * @copyright        Copyright (c) 2007, Alan Blount
 * @version          0.1
 * @modifiedby       alan [a4] zeroasterisk [d07] com
 * @license          http://www.opensource.org/licenses/mit-license.php The MIT License
 *
 * == Info ==
 * caches arrays or strings... good for $this->requestEvent(), and just as good for a Database Query Result Set...
 * 
 * version below includes optional fields: $controller, $action, $id, $userid, $repid
 * most of those fields inherit from the controller if empty... (left the code as simple as possible for easy reconfiguration)
 * --------
 * Can clear at any point with cake helper function: clearCache();
 */

class EcacheComponent extends Object {
    var 
$duration '+2 hours';
    var 
$controller$id$userid$repid// may be used later
    
function startup(&$controller) {
        
$this->controller = &$controller;
        if (isset(
$this->controller->id)) {
            
$this->id $this->controller->id;
        }
        if (isset(
$this->controller->Uid)) {
            
$this->userid $this->controller->Uid;
        }
        if (isset(
$this->controller->repid)) {
            
$this->repid $this->controller->repid;
        }
    }
    
    function 
ecache($data=null$controller=null$action=null$id=null$userid=null$repid=null$duration=null) {
        
// set values
        
if (empty($controller)) {
            if (isset(
$this->params['controller'])) {
                
$controller $this->controller->params['controller'];
            } else {
                
$controller 'unknown';
            }
        }
        if (empty(
$action)) {
            if (isset(
$this->params['action'])) {
                
$action $this->controller->params['action'];
            } else {
                
$action 'unknown';
            }
        }
        if (empty(
$id)) {
            if (isset(
$this->id)) {
                
$id intval($this->id);
            } elseif (isset(
$this->controller->id)) {
                
$id intval($this->controller->id);
            } else {
                
$id intval($this->id);
            }
        }
        if (empty(
$userid)) {
            if (isset(
$this->controller->userid)) {
                
$userid intval($this->controller->userid);
            } else {
                
$userid intval($this->userid);
            }
        }
        if (empty(
$repid)) {
            if (isset(
$this->controller->repid)) {
                
$repid intval($this->controller->repid);
            } else {
                
$repid intval($this->repid);
            }
        }
        if (empty(
$duration)) {
            if (isset(
$this->controller->ecache_duration)) {
                
$duration $this->controller->ecache_duration;
            } else {
                
$duration $this->duration;
            }
        }
        if (
is_array($data) || is_object($data)) {
            
$data serialize($data);
        }
        
// make cache path & filename
        
$filename $controller.'_'.$action.'_'.$id.'_'.$userid.'_'.$repid;
        
$replace = array('&''~''!'','';'':''*''__''__''__');
        
$path_key str_replace($replace'_'$filename);
        
$cachePath 'views'.DS.$path_key.'.php';
        
// do cache.... if data=null, retrieve... else, write & return
        
$re cache($cachePath$data$duration);
        
// return data (attempt unserialize)
        
$d = @unserialize($re);
        if (
$d!==false && $d!==null) {
            return 
$d;
        } else {
            return 
$re;
        }
    }
    
    
// convenience wrapper for "clearCache"
    
function clear() {
        return 
clearCache();
    }
    
    
// convenience wrapper for "ecache"
    
function c($data=null$controller=null$action=null$id=null$userid=null$repid=null$duration=null) {
        return 
$this->ecache($data$controller$action$id$userid$repid$duration);
    }
}
?>

Login to Submit a Comment