WordPress Caching, part 3: Custom Caching Library

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:

  1. I was doing things with public apis that have an hourly request limit, so I had to build some sort of data cache.
  2. Whilst wp_super_cache and W3 Total Cache are well known there’s no guarantee people will use it.
  3. 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.

WordPress News

The latest WordPress updates from the WPBriefs Podcast.

Related Posts

28 May 2010

WordPress caching, Part 2

As I mentioned in WordPress caching part 1, WordPress has built-in caching that can be hooked into by plugins such as W3 Total Cache and Batcache (developed by Andy Skelton who is employed by Automattic).In this article I am going...
08 Apr 2010

WordPress Caching, Part 1: The Basics

Caching (on the internet) is the act of storing computationally expensive calculations in a way that can be recovered very quickly with the smallest possible impact on the server.Or, in short, ‘speeding stuff up’.In this series of posts I will...
23 Oct 2012

WordPress Pagination with Custom WordPress Queries

I don’t remember the last time I made a WordPress theme that didn’t do all sorts of unique stuff. I’ve never been interested in making standard blog designs and always want to create something a bit different. This throws up...
09 Jul 2010

Lowercase p, dangit! WordPress Controversy

There has recently been a new piece of code added to the WordPress core which makes sure that people spell WordPress correctly – automatically correcting misspellings (ie. making the P in the middle uppercase).On its own this seems harmless enough...
05 Sep 2016

MasterWP – A Free Course to Improve Your WordPress Skills

As a premium theme seller my target audience is implementors, people who buy themes for clients and then customize them. But how do people get to be implementors to start with? This is something I wanted to tackle – helping...