Listing 2. Associating an Arbitrary Function with the Script Termination Event

<?php
// path where cache files are stored
$CACHE_PATH="/tmp";

// cache time out in seconds
$CACHE_TIMEOUT=10;

// this script URL
$SCRIPT_URL="http://".$HTTP_HOST.$PHP_SELF;

// create cache file name based on
// the script name and the cache path
function cachefilename() {
global $PHP_SELF,$CACHE_PATH;

   return($CACHE_PATH."/".md5($PHP_SELF).".cache");
}

// check whether the script needs caching
function needscache($timeout) {
   clearstatcache();
   if (time()-filemtime(cachefilename())>$timeout)
      return(true);
   else
      return(false);
}

// read cache file and send it to the browser
function outputcache() {
   readfile(cachefilename());
}

// cache the script
function docache($buffer) {

   // write the script output into
   // the cache file
   $fp=fopen(cachefilename(),"w");
   if ($fp)
      fputs($fp,$buffer);

   // send the script output to
   // the browser
   return($buffer);
}

// cache the script after it finishes
function doaftercache() {
global $SCRIPT_URL;

   // read the script output
   $fp=fopen($SCRIPT_URL,"r");
   while (!feof($fp))
      $buffer.=fgets($fp,4096);

   // write the script output into
   // the cache file
   $fp=fopen(cachefilename(),"w");
   if ($fp)
      fputs($fp,$buffer);
   fclose($fp);
}

if (needscache($CACHE_TIMEOUT)) {
   // the script needs caching
   if (file_exists(cachefilename())) {
      register_shutdown_function("doaftercache");
      outputcache();
      exit();
   } else
      ob_start("docache");
} else {
   // the script is cached so let's read
   // from the cache and exit
   outputcache();
   exit();
}
?>