Ben
Ben is a lifelong Nintendo fan who likes to build websites, and make video games. He buys way too much Lego.
WordPress and Games
When building Elemental (WordPress Theme) I decided to develop my own, very simple, caching plugin to help speed up the theme.
There were a few reasons why I did it but the main ones were:
My objectives when coding it were simple and follow my personal code desires. I wanted something small, clean, and fast – and hopefully I achieved all three.
I ended up writing a library of functions that get and set cache values – and since I like to share I thought I would open it up. The library is just a series of functions and it can actually be repurposed for any PHP application really easily. Maybe others will find a use for it or, even better, offer improvements.
<?php /** * cachePut * Save Cache files to cache directory * * @param string $id cache key - unique string for saving and retrieving cache data * @param mixed $data data to save to cache * @return boolean */ function bm_cachePut ($id = '', $data = NULL) { // make sure required values are visible if ($id == '' || $data == NULL) { return FALSE; } if ($handle = @fopen(bm_cacheName ($id), 'w')) { fwrite($handle, serialize ($data)); fclose($handle); return true; } else { echo ''; } return false; } /** * cacheGet * Retreive the cache using the unique key specifying an expiration age so that the cache can be refreshed * * @param string $id cache key - unique string for saving and retrieving cache data * @param integer $expires time in seconds that the cache file can live for before being refreshed * @return array */ function bm_cacheGet ($id = '', $expires = 0) { if ($expires == 0) { $expires = BM_CACHE_TIME; } // add on random 10 percent of the expire time to add some randomness // will mean all caches on one page for same time frame do not expire at the same time $expires = $expires + ceil (rand (1, ($expires / 10))); $filename = bm_cacheName ($id); $filenameExists = file_exists ($filename); if ($filenameExists) { $age = (time() - filemtime ($filename)); //echo ''; if ($age
As you can see, it’s very straight forward. There are four functions and they fo the following:
To make use of the cache library I created another function that “gets” the “content”. This function makes use of the WP_Http class that I wrote about recently.
<?php function bm_getContent ($url, $cacheTime = 60, $prefix = 'getContent') { $cachename = $prefix . '_' . md5($url . $cacheTime); $content = ''; if (!$content = bm_cacheGet($cachename, $cacheTime)) { $request = new WP_Http; $result = $request->request($url); if (!isset($result->errors)) { $content = $result['body']; } bm_cachePut ($cachename, $content); } if ($content != '') { return $content; } else { return FALSE; } } ?>
To use it all you have to do is use the code below and it will automatically cache the request for 1 minute:
<?php $content = bm_getContent ('url_to_cache'); ?>
A real life example could be with the Yahoo! weather code I wrote about a few months ago.
<?php function bm_getWeather ($code = '', $temp = 'c') { $file = 'http://weather.yahooapis.com/forecastrss?p=' . $code . '&u=' . $temp; $data = bm_getContent($file); $output = array ( 'temperature' => bm_getWeatherProperties('temp', $data), 'weather' => bm_getWeatherProperties('text', $data), 'weather_code' => bm_getWeatherProperties('code', $data), 'class' => 'weatherIcon-' . bm_getWeatherProperties('code', $data), ); return $output; } function bm_getWeatherProperties ($needle, $data) { $regex = ''; preg_match($regex, $data, $matches); return $matches[1]; } ?>
I’d be careful about using a disk cache for WordPress, unless you know specifics about the server setup. For instance, using a disk based cache can actually make performance worse in some setups, usually where the “disk” is actually mounted over the network. This can be particularly common in shared server environments.
Disk caching has another challenge, it focuses on a single web server. That can cause problems for sites that use more than one front end web server.
As a general solution, in the context of WordPress, I’d push that data into options. An added benefit of that approach is that if they do have an object cache plugin installed (say for memcached for instance) then you’ll get the benefit of that automatically, not extra work needed.
Hey Joseph – thanks for the feedback. Would you recommend that for things like caching feeds/ xml (from Twitter api for example) as well?
What are your opinions of plugins like WP_Super_Cache that do page caching on disk? In my opinion (and experience) small sites generally don’t have any problems with using a disk based cache – it’s larger sites with many visitors that get into problems have lots of disk based activity.
Disk based caching is fine, under certain server setups. The assumption is that an admin installing WP_Super_Cache knows if his server setup will benefit, and not get worse, from using it. If a theme or plugin tries to do it’s own disk based cached, it usually isn’t obvious to the admin (without looking at the code), so he doesn’t get the opportunity to make the same specific decision about how caching should work on their particular site.
As for caching feeds or Twitter XML data, should be fine. WordPress itself uses options to cache the admin dashboard feeds.
Hey Joseph, thanks again for the feedback. I think I am going to add db based caching to my todo list and maybe make it a user configurable option.
I think the assumption that people know the limitations of WP_Super_Cache is wrong though. My guess is that most people will see something like a statement that reads “WP_Super_Cache will speed up your website” and then install it – irrespective of the server setup. My guess is that those who are (or have hired) knowledgeable System Admins are unlikely to need WP_Super_Cache anyway, as they will be using something like Memcached… which actually kind of proves your point, and means I should use the built in WP caching object even more than I do.
Agreed, no doubt that people have installed WP_Super_Cache without looking at their environment closely enough to see if it will help or hurt. My point was more that an admin installing a caching plugin is at least more likely to know if it will help or not, than a theme or plugin that does it blindly (everywhere it is installed).
I expect at some point there will be hosting providers that leverage these caching plugins. It would be great if they were integrated right into the one-click installs that many of them have. Then again, I’ve been saying this for a few years.
we all have problems with wp catching and still i couldnt find the right solution ..
as much as i do is les querries or try to have more badswitch.. does anyone know catching system with multilanguage wp site
Hi Ben,
off topic,
just want to let you know that
i see in my rss feed,
two of your posts images use
the “I took this images” warning,
I just thought that it was only in my google reader
but after visiting the posts, both posts use the warning images,
i’m pretty sure that you didn’t intend to use it as your post images.
hope it help,
Dian
Hey Dian – thanks for the message. The problem occurs because I am using a cdn and the ‘you stole the images’ image is being cached by the cdn instead of the real image. I think I have fixed the problem but if I haven’t then I will remove the code.
Ben, thanks so much for this, I definitely have a need for just this type of solution, as I find the caching plug-ins to be swiss-army type tools, without granular or low-level caching I need, when building apps which work with WordPress.
Cheers
Glad you found it useful 🙂
Have a question… I’ve used both w3 and wp super cache.
If I have a low server load on my shared server running wordpress with traffic under 10,000 page loads a day; w3 blows supercache out of the water
Once I start getting to around 150K pageloads a day running w3 my server is basically nonfunctional. With wp supercache it’s still not even sweating…
I’ve tried both disk and memory based caching in w3 and database caching on and off; makes no difference when exp high traffic.
Any ideas?
Hey Craig – I don’t have any ideas I’m afraid. I do know that W3 Total Cache is considerably more complicated so I guess the additional processing it does to minify content etc is what is weighing down the server.
I use W3 Total Cache here and love it, but I agree with you, I am thinking about swapping back to WP Super Cache to compare page load speed. Will be interesting to see the results.
we all have problems with wp catching and still i couldnt find the right solution ..
as much as i do is les querries or try to have more badswitch.. does anyone know catching system with multilanguage wp site
Hi Ben,
off topic,
just want to let you know that
i see in my rss feed,
two of your posts images use
the “I took this images” warning,
I just thought that it was only in my google reader
but after visiting the posts, both posts use the warning images,
i’m pretty sure that you didn’t intend to use it as your post images.
hope it help,
Ben, thanks so much for this, I definitely have a need for just this type of solution, as I find the caching plug-ins to be swiss-army type tools, without granular or low-level caching I need
we all have problems with wp catching and still i couldnt find the right solution ..
as much as i do is les querries or try to have more badswitch.. does anyone know catching system with multilanguage wp site