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:
- I was doing things with public apis that have an hourly request limit, so I had to build some sort of data cache.
- Whilst wp_super_cache and W3 Total Cache are well known there’s no guarantee people will use it.
- I thought it would be interesting to learn how.
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.
BM_Cache Library
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.
<pre style="height:500px;"><?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:
- bm_cachePut – This saves the specified data to a cache file with the specified key
- bm_cacheGet – load the data for the specified cache key. Uses a time parameter to set how long the cached data should live for before being reset
- bm_cacheName – This converts the cache key into the file name for the cached content
- bm_cacheKill – Delete a cache file based upon it’s key
Usage
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 = '<yweather .="" :condition.=""></yweather>';
preg_match($regex, $data, $matches);
return $matches[1];
}
?>
Was it good/ useful/ a load of old rubbish? Let me know on Mastodon, or BlueSky (or Twitter X if you must).
Link to this page
Thanks for reading. I'd really appreciate it if you'd link to this page if you mention it in your newsletter or on your blog.