Instant caching with PHP
I’ve been getting more database timeout errors today, probably due to increased traffic from links to recent entries. A permanent solution would be to switch to generating static HTML (this site is currently dynamically generated for every request), but I don’t have time for a full re-write at the moment. Luckily, PHP offers an extremely simple solution to dynamic caching in the form of output buffering. The front page of the site (which generates by far the most traffic) is now served from a cached copy if it has been cached within the last 5 minutes. Best of all, I didn’t have to edit any of my core application logic—I just dropped in some extra code at the top and bottom of the index.php file. Here’s how it works:
<?php
$cachefile = 'cache/index-cached.html';
$cachetime = 5 * 60;
// Serve from the cache if it is younger than $cachetime
if (file_exists($cachefile) && time() - $cachetime < filemtime($cachefile)) {
include($cachefile);
echo "<!-- Cached copy, generated ".date('H:i', filemtime($cachefile))." -->\n";
exit;
}
ob_start(); // Start the output buffer
/* The code to dynamically generate the page goes here */
// Cache the output to a file
$fp = fopen($cachefile, 'w');
fwrite($fp, ob_get_contents());
fclose($fp);
ob_end_flush(); // Send the output to the browser
?>
I’ve added a few extra bits of logic to check that the page being cached isn’t itself a database error page, but the above is the bulk of the code. Best of all, due to the nature of output buffering it should work on practically any PHP application.
jim winstead - 6th May 2003 00:31 - #
Different idea: Whenever you add a post, update your blogroll, or add a comment to the site, touch a file. When a request for the index page comes in, compare the timestamp on the file to the timestamp on the cached copy. If you ever update the code on your index page, just delete the timestamp file.
You can also go on and do caching properly. I've a blog that's been sitting half-written on my hard drive for months that already handled all sorts of caching situations (last-modified, etags, conditional gets, pipelining, etc). It's not hard, but you need to pay attention when testing, and test very thoroughly.
Jim - 6th May 2003 01:50 - #
Eventually I'm going to sit down and write something better, but what I've been doing is just having
lynx --sourcerun on a cron job every 2 minutes and dump index.php -> index.html for my front page. Things such as the blogroll change commonly enough that I wouldn't benefit much from doing some sort of elaborate scheme that figured out what has changed, etc., and the front page is as fast as a perfectly static file from Apache. I also have a link to index.php in my header so if anyone really wants to see the latest and greatest, they can. Actually, it's more for me.For WordPress I've been considering something akin to a funky caching system that generates static files and uses a method similar to Jim's except instead of touching a file it touches a field in the database. However Smarty caching is looking smooth enough that this might not even be an issue. It looks like I'll be able to take the best of baked and fried (was it fried?) without messing with writing to the filesystem.
Matt - 6th May 2003 02:53 - #
Swannie - 6th May 2003 19:43 - #
Andy - 2nd June 2004 16:24 - #
klkjljk - 13th September 2005 21:10 - #
Not Given - 3rd February 2006 22:11 - #
asd - 25th April 2006 14:09 - #
Kyle Lougnot - 27th May 2006 06:40 - #
Marcel - 14th August 2006 21:59 - #
Thanks Simon !
3 years later and your post is still of great help for many of us... especially usefull for fetching RSS Feeds...
Thank you
Tim - 22nd October 2006 23:17 - #