» November 2011 - improved code click here to view

There are many tools around that will help cache your website to increase speed and performance, such as eAccelerator and APC. However these usually require installation on your web server, thus rendering them useless for people who use shared hosting and don’t have access to the server.

Using some simple PHP code we can quite effectively cache a webpage, useful for sites that are database driven and have a large amount of queries or high volumes of traffic.

First we need to setup the folder where the cached files are stored, making sure it has read/write permissions (CHMOD to 0777 – see your FTP client documentation on how to do this).

Next create a file called cache.php which contains the following code:

<?php
// Number of seconds a page should remain cached for
$cache_expires = 3600;

// Path to the cache folder
$cache_folder = "/home/usr/www/cache/";

// Checks whether the page has been cached or not
function is_cached($file) {
	global $cache_folder, $cache_expires;
	$cachefile = $cache_folder . $file;
	$cachefile_created = (file_exists($cachefile)) ? @filemtime($cachefile) : 0;
	return ((time() - $cache_expires) < $cachefile_created);
}

// Reads from a cached file
function read_cache($file) {
	global $cache_folder;
	$cachefile = $cache_folder . $file;
	return file_get_contents($cachefile);
}

// Writes to a cached file
function write_cache($file, $out) {
	global $cache_folder;
	$cachefile = $cache_folder . $file;
	$fp = fopen($cachefile, 'w');
	fwrite($fp, $out);
	fclose($fp);
}

// Let's begin, first work out the cached filename
$cache_file = md5($_SERVER['REQUEST_URI']) . ".html";

// Check if it has already been cached and not expired
// If true then we output the cached file contents and finish
if (is_cached($cache_file)) {
	echo read_cache($cache_file);
	exit();
}

// Ok so the page needs to be cached
// Turn on output buffering
ob_start();

Now in your page you would include cache.php on the first line before you do anything else. This is because if the page is cached we don't want it to do anything else other than output the cache to the page. If you are still including other files or connecting to databases before checking for the cache you are putting additional load on the server, making this exercise pointless.

Finally create a file called cache_footer.php which contains the following code:

<?php
// Grab the uncached page contents
$cache_contents = ob_get_contents();

// Save it to the cache for next time
write_cache($cache_file, $cache_contents);
?>

You would include this file on the last line of your page, which saves the page in the cache if required.

Putting it altogether a typical page would look like this:

<?php
// Load the cache process
include("cache.php");

// Connect to database
include("config.php");
mysql_connect($db_host, $db_username, $db_password) or die(mysql_error());
mysql_select_db($db_name) or die(mysql_error());
?>
<html>
<body>
<h1>Articles</h1>
<ul>
<?php
// Some query
$q = mysql_query("SELECT * FROM articles ORDER BY id");
while ($r = mysql_fetch_array($q)) {
  echo '<li><a href="view_article.php?id='.$r['id'].'">'.$r['title'].'</a></li>';
}
?>
</ul>
</body>
</html>
<?php
// Save the cache
include("cache_footer.php");
?>