Home arrow PHP arrow Page 3 - Caching Result Sets in PHP: A Content-Change Triggered Caching System

Another caching strategy: building a content-change triggered caching system - 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.

TABLE OF CONTENTS:
  1. Caching Result Sets in PHP: A Content-Change Triggered Caching System
  2. Back to the origins: a quick overview of the time expiry based caching script
  3. Another caching strategy: building a content-change triggered caching system
  4. Wrapping the code: defining the “readData()” and “readQueryResult()” functions
  5. Gluing the pieces together: listing the whole source code
By: Alejandro Gervasio
Rating: starstarstarstarstar / 4
October 12, 2005

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

As I said before, there are different ways to develop a caching system. In this case we’ll create a script that triggers the caching process when a modification has been introduced to the data. We’ll reuse the functions previously defined in the first article, so the new script shouldn’t present any difficulties.

The logic of the script is very understandable, as you’ll see shortly. It simply runs randomly a SQL SELECT statement and verifies whether the newly obtained data is the same as the cached data. If it is not, then the new result set is retrieved and stored again in the cache file. Otherwise, the data is directly read from the cache file. This sounds simple and looks simple too. Therefore, let’s see the complete source code for the script and next proceed to explain each relevant section.

The content-change triggered cache 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';
// 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
                        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;
                        }
                        // 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
            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 />';
}

As you can see, we’ve reused most of the existing functions for reading and writing the cache file, as well as the functions to connect to MySQL and run SQL queries. However, the noticeable difference compared to the previous method resides on the cache trigger. We use a random positive integer value to determine when to run the query and return a new result set, and then compare it to the cached data. The following snippet illustrates this condition:

if(rand(1,100)>90){
            // read randomly 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;
            }
            // 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);
}

In this case, I’ve used the “rand()” function to obtain a random number between 1 and 100. If the value is greater than 90, the query is run. Next, the “fresh” data is compared to the cached data by performing a MD5 hashing algorithm on each value. If the data has changed, the cache is regenerated, and the new data is returned for processing. Otherwise, the data is simply read from the cache file.

The data comparison is carried out through the following expression:

(md5(serialize($cacheData))==md5(serialize($data)))?
$data=$cacheData:writeCache($data,$cacheFile);

Indeed, not only is the script fairly easy to be understood, but it supports many improvements. Feel free to make the proper modifications to suit your specific needs, as long as you’re using a procedural approximation.

Finally, the overall code might be wrapped into a pair of containing functions, in order to hide all of the internal processing, and focus on the handled data rather than the functions. Therefore, let’s complete the next step, by defining the new “readData()” and “readQueryResult()” function. Don’t you worry, it’s only a few lines away.



 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: