HomePHP Page 2 - Caching Result Sets in PHP: A Content-Change Triggered Caching System
Back to the origins: a quick overview of the time expiry based caching script - PHP
Caching within the context of PHP application acceleration can be triggered based on three possible categories: time expiry, content change, and manually. This article covers an application that triggers the caching mechanism based on a content change condition.
In order to set up the starting point for developing the new version of the caching system, let’s touch briefly on the previous script, so we may better understand the basics of caching.
As you probably remember, the script relies strongly on the use of the “serialize()” and “unserialize()” functions, as a straightforward and efficient technique for converting a entire result set array into a byte-stream string that represents its values and structure. Once the result set has been serialized, it’s possible to accomplish post processing on it, including caching tasks.
Therefore, here is the set of basic functions that compose the original procedural caching system:
function writeCache($data,$cacheFile='default_cache.txt'){ if(!$fp=fopen($cacheFile,'w')){ trigger_error('Error opening cache file'); exit(); } if(!flock($fp,LOCK_EX)){ trigger_error('Unable to lock file'); exit(); } if(!fwrite($fp,serialize($data))){ trigger_error('Error writing to cache file'); exit(); } flock($fp,LOCK_UN); fclose($fp); } function readCache($cacheFile){ if(!file_exists($cacheFile)){ trigger_error('Invalid cache file'); exit(); } return unserialize(file_get_contents($cacheFile)); } function connectMySQL($host,$user,$password,$database){ if(!$db=mysql_connect($host,$user,$password)){ trigger_error('Error connecting to the server '.mysql_error()); exit(); } if(!mysql_select_db($database,$db)){ trigger_error('Error selecting database '.mysql_error()); exit(); } } function query($query){ if(!$result=mysql_query($query)){ trigger_error('Error performing query '.$query.mysql_error()); exit(); } return $result; } function readData($options=array (),$expireTime=7200,$cacheFile='default_cache.txt'){ // check parameters if(count($options)<5){ trigger_error('Invalid number of parameters'); exit(); } // create connection variables foreach($options as $key=>$value){ ${$key}=$value; } // check if query starts with SELECT if(!preg_match("/^SELECT/",$query)){ trigger_error('Invalid query. Must start with SELECT'); exit(); } // check to see if cache file is valid (time triggered caching) if(file_exists($cacheFile)&&filemtime($cacheFile)>(time()-$expireTime)){ // read data from cache file $data=readCache($cacheFile); } else{ // read data from MySQL connectMySQL($host,$user,$password,$database); $result=query($query); // store result set in array while($row=mysql_fetch_array($result,MYSQL_ASSOC)){ $data[]=$row; } // store serialized data in cache file writeCache($data,$cacheFile); } return $data; }
And below is a possible implementation, where the result set is cached for 24 hours:
// read data from MySQL or cache file $options=array('host'=>'host','user'=>'user','password'=>'password','database'=>' database','query'=>'SELECT * FROM users'); $data=readData($options,86400,'cache_file.txt'); // display data foreach($data as $key=>$row){ echo 'First Name :'.$row['firstname'].' Last Name :'.$row ['lastname'].'<br />'; }
Certainly, the relevant functions of the script are “readCache()” and “writeCache()”, which first serializes the data, then unserializes it by restoring it to its original structure. For rather simple applications, this caching solution might be easily put to work with minor changes, since it’s quite versatile and portable. It’s just a matter of tweaking the code a bit to suit specific needs.
All right, until now we’ve seen our first approximation for working with a procedural caching system. Therefore, the next step is to code a new script that triggers the cache when the data has been modified in some way. Want to see more? Okay, just keep on reading.