Caching Result Sets in PHP: Cost-efficient PHP acceleration - A fully functional result set caching system: modifying the original script (
Page 3 of 4 )
In order to implement a functional result set caching system, we need to make some changes to the original version of the script, so we can take advantage of the data stored in the cache file, directly reading the result set from that file. Also, it's important to clarify that the script will use a time triggered caching approach, thus forcing a new cache generation each time an expiry timestamp is reached.
Therefore, having defined the overall features of the caching system, the brand new version of the script looks like this:
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;
}
// define cache file
$cacheFile='cacheFile.txt';
// define expire time in seconds (2 hours)
$expireTime=7200;
// 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','databasename');
$result=query('SELECT * FROM users');
// store result set in array
while($row=mysql_fetch_array($result,MYSQL_ASSOC)){
$data[]=$row;
}
// store serialized data in cache file
writeCache($data,$cacheFile);
}
// display data
foreach($data as $key=>$row){
echo 'First Name :'.$row['firstname'].' Last Name :'.$row['lastname'].'<br />';
}
Okay, let's break down the code to analyze in detail the tasks accomplished by each section. First, we've defined some wrapping functions that take care of reading and writing data to the cache file, along with other simple functions that connect to MySQL, select a database and execute a query.
But let's take a look at the "writeCache()" function. As you can see, it accepts two parameters: the data to be written to the cache file, and the name of the cache file being used. This function simply writes serialized data to the given cache file, so in this case the serialized data will be the array obtained from a result set. The referenced function is listed below:
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);
}
Notice that I'm using a generic file locking method when writing data to the cache file. However, this might not work properly on some network operating systems. So, be aware of this, in order to implement a file locking method that works in the operating system of your choice.
Now, let's have a look at the "readCache()" function, which reads from the cache file, by reversing the serialized data, and restoring it to its original state:
function readCache($cacheFile){
if(!file_exists($cacheFile)){
trigger_error('Invalid cache file');
exit();
}
return unserialize(file_get_contents($cacheFile));
}
The only thing to note here is how the data is returned by the function, as stated previously, by using the "unserialize()" function, which is listed below:
return unserialize(file_get_contents($cacheFile));
By now, we've defined the most relevant functions for implementing the result set caching system. As you might guess, the rest of the functions are fairly self-explanatory. They connect to MySQL, then select a database and finally perform a given query. Here's the list of each one of them, beginning with the "connectMySQL()" function:
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();
}
}
Lastly, the "query()" function:
function query($query){
if(!$result=mysql_query($query)){
trigger_error('Error performing query '.$query.mysql_error());
exit();
}
return $result;
}
I'm sure that you've used similar functions hundreds of times, so I won't spend time on them. Instead, I'll focus primarily on the logic of the caching script. Thus, join me in the next explanation to see how this caching system can be put quickly into action. Let's go!