Magic Memcached
I had a pretty standard pattern for memcaching expensive method calls:
$key = "MyKey";
if(!$data = MC::get($key)){
$data = some_expensive_function();
MC::set($key, $data);
}
do_stuff($data);
But I guess I copied and pasted that pattern one too many times, and decided that there really has to be a better way. Thanks to the overloading methods in PHP 5 and late static bindings in PHP 5.3.0, there is!
Let’s take a look at the code:
This class uses PHP’s __call and __callStatic magic methods to intercept any method call which does not result in a method actually being executed. We then look for two prefixes, mc_ or mcd_ to determine if the method call was intended to be processed through our cache wrapper. If we find one of those prefixes, we rewrite the method name and attempt to call the new method and cache the result.
Pretty simple concept, and super easy to use. To use this on a pre-existing class, just extend the Memcacheable class and you’re good-to-go. Here’s a fairly contrived example of a class that is now magically memcached:
And an example of how you would actually interact with the caching mechanisms:
As always, I have a few notes:
mc_will cache the code,mcd_will delete the code from the cache__callStaticandget_called_class()require PHP 5.3.0 or greater, if you don’t care about caching calls to static methods you can remove the__callStaticblock fromMemcacheable.phpand it should all work in PHP 5.0 or greater- I’m referencing an imaginary Memcached wrapper class called
MC, you’ll need to replace these calls with calls to your own cache wrapper. I’ve provided a terribly simplistic implementation in the gist so that the code can all be run together - One of the downsides of the approach is that
__callprevents errors about calls to undefined methods from being thrown. It’s fine because we can throw our own error, but it feels fairly sloppy
Discussion on Hacker News