Skip to content

Instantly share code, notes, and snippets.

@nickyleach
Created April 16, 2011 17:20
Show Gist options
  • Save nickyleach/923312 to your computer and use it in GitHub Desktop.
Save nickyleach/923312 to your computer and use it in GitHub Desktop.
PHP class which allows you to magically memcache method calls (with example)
<?
require 'Memcacheable.php';
class Foo extends Memcacheable {
public function __construct(){
$this->widget = "widget";
}
public function bar($arg){
sleep(2);
return "{$this->widget} - $arg\n";
}
public static function baz($arg){
sleep(2);
return "$arg\n";
}
}
?>
<?
require 'Foo.php';
$key1 = "key1";
$key2 = "key2";
$foo = new Foo();
echo $foo->mc_bar($key1); // Not cached
echo $foo->mc_bar($key1); // Cached
echo $foo->mcd_bar($key1); // Key deleted
echo $foo->mc_bar($key1); // Not cached
// Caching is separate for static and non-static calls
echo Foo::mc_baz($key2); // Not cached
echo $foo->mc_baz($key2); // Not cached
echo Foo::mc_baz($key2); // Cached
echo $foo->mc_baz($key2); // Cached
?>
<?
class MC {
public static $cache = array();
public static function delete($key){
unset(self::$cache[$key]);
}
public static function get($key){
if(!isset(self::$cache[$key])){
throw new Exception("Key $key not set");
} else {
return self::$cache[$key];
}
}
public static function key($key){
return md5($key);
}
public static function set($key, $value){
self::$cache[$key] = $value;
}
}
?>
<?
require 'MC.php';
class Memcacheable {
public function __call($method, $args){
try {
return self::_memcacheCall($this, $method, $args);
} catch(Exception $e){
$backtrace = debug_backtrace();
trigger_error("Call to undefined method {$backtrace[1]['class']}->$method in {$backtrace[1]['file']} on line {$backtrace[1]['line']} ---\n\n" , E_USER_ERROR);
exit;
}
}
public static function __callStatic($method, $args){
try {
return self::_memcacheCall(get_called_class(), $method, $args);
} catch(Exception $e){
$backtrace = debug_backtrace();
trigger_error("Call to undefined method {$backtrace[1]['class']}::$method in {$backtrace[1]['file']} on line {$backtrace[1]['line']} ---\n\n" , E_USER_ERROR);
exit;
}
}
private static function _memcacheCall($context, $method, $args){
if(stristr($method, 'mc_')){
$method = str_replace('mc_', '', $method);
if(method_exists($context, $method)){
return self::_memcacheExecuteCode($context, $method, $args);
}
} elseif(stristr($method, 'mcd_')){
$method = str_replace('mcd_', '', $method);
if(method_exists($context, $method)){
return self::_memcacheExpireCode($context, $method, $args);
}
}
throw new Exception("Method $method does not exist");
}
private static function _memcacheExecuteCode($context, $method, $args){
$key = self::_memcacheKey($context, $method, $args);
// MC::get() throws an exception when the key does not exist
try {
$result = MC::get($key);
} catch(Exception $e){
$result = call_user_func_array(array($context, $method), $args);
MC::set($key, $result);
}
return $result;
}
private static function _memcacheExpireCode($context, $method, $args){
$key = self::_memcacheKey($context, $method, $args);
MC::delete($key);
}
private static function _memcacheKey($context, $method, $args){
return MC::key(( is_string($context) ? "s_$context" : "o_" . get_class($context) ) . ":$method:" . serialize($args));
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment