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];
}
?>
How was it for you? Let me know on BlueSky or Mastodon
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.