ecache - easy per user or per anything cache of html or arrays
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.
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.
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);
}
}
?>
Latest Comments