HomePHP Page 5 - Caching Result Sets in PHP: A Content-Change Triggered Caching System
Gluing the pieces together: listing the whole source code - 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.
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 readQueryResult($options=array()){ // check parameters if(count($options)<5){ trigger_error('Invalid number of parameters'); exit(); } // create connection variables foreach($options as $key=>$value){ ${$key}=$value; } // connect to MySQL if(!mysql_connect($host,$user,$password)){ trigger_error('Error connecting to the server '.mysql_error()); exit(); } // select database if(!mysql_select_db($database)){ trigger_error('Error selecting database '.mysql_error()); exit(); } // check if query starts with SELECT if(!preg_match("/^SELECT/",$query)){ trigger_error('Invalid query. Must start with SELECT'); exit(); } if(!$result=mysql_query($query)){ trigger_error('Error performing query '.$query.mysql_error()); exit(); } while($row=mysql_fetch_array($result,MYSQL_ASSOC)){ $data[]=$row; } return $data; } function readData($options=array(),$cacheFile='default_cache.txt'){ // check to see if cache file is valid (content changed triggered caching) if(file_exists($cacheFile)){ if(rand(1,100)>90){ // read randomly data from MySQL $data=readQueryResult($options); // read cache data $cacheData=readCache($cacheFile); // compare cached data with fresh data // if content has changed then force new cache generation (md5(serialize($cacheData))==md5(serialize($data)))? $data=$cacheData:writeCache($data,$cacheFile); } else{ // read data from cache file $data=readCache($cacheFile); } } else{ // read data from MySQL $data=readQueryResult($options); // store data in cache file writeCache($data,$cacheFile); } return $data; } // read data from MySQL-cache file $options=array('host'=>'host','user'=>'user','password'=>'password','database'=> 'databasename','query'=>'SELECT * FROM users'); $data=readData($options,'cache_file.txt'); // display data foreach($data as $key=>$row){ echo 'First Name :'.$row['firstname'].' Last Name :'.$row ['lastname'].'<br />'; }
At this point, we’ve developed a procedural solution that uses the nice advantages of result caching to reduce the overhead of making many connections to a database, running queries and getting results. Through the usage of the serialize-unserialize sequence, we’re able to build faster and more efficient PHP applications.
Summarizing
That’s about it for now. In this second part we’ve looked in detail at another result set caching system. It is triggered by a content change condition, by running randomly a SELECT query, in order to determine whether the data has been modified, and behaves accordingly. The result will be returned either from the database or the cache file.
While this method is suitable for small applications and certainly supports many modifications, we need to go further on this topic. Thus, over the third part of the series, we’ll definitely take the object-oriented approach, by developing a set of classes that work together to implement result set caching in large applications. Until then, stay tuned.