Home arrow PHP arrow Page 4 - Caching Result Sets in PHP: Cost-efficient PHP acceleration

Putting the pieces together: implementing the result set caching script - PHP

With many websites using a database backend for storing and delivering content, certain common problems arise. One of these is a situation that causes the server to slow down or even bring the system to a complete halt. What can you do to reduce the load on your server? This tutorial discusses one method, a result set caching system, and demonstrates how to implement it with either a procedural or an object-oriented approach.

TABLE OF CONTENTS:
  1. Caching Result Sets in PHP: Cost-efficient PHP acceleration
  2. The first caching approximation: serializing and unserializing data
  3. A fully functional result set caching system: modifying the original script
  4. Putting the pieces together: implementing the result set caching script
By: Alejandro Gervasio
Rating: starstarstarstarstar / 23
October 03, 2005

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

Undoubtedly, there is much to be gained by implementing a caching system like this. If a website delivers content that doesn't change very frequently, let's say by offering a list of articles or products, we might be able to cache the data in a file and force a new cache generation based on a time expiry caching strategy.

In this case, the script follows that approach, establishing a time expire value in seconds for the validity of the cache file. The first occurrence of the script connects to MySQL and obtains the corresponding result set, which after being serialized, is cached to the file. As a result, all of the subsequent page requests will display the data retrieved from the cache, until the time expiry will be reached.

The above logic is better understood by looking at the code listed below:

// 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 />';
}

As you can see, the above script first defines to the cache file where to store the result set, in this case "cacheFile.txt". Then, it specifies the time period, expressed in seconds, for considering the cached data valid. For this particular example, I've specified a cache validity of two hours (7,200 seconds). These values are defined in the following lines:

// define cache file
$cacheFile='cacheFile.txt';
// define expire time in seconds (2 hours)
$expireTime=7200;

As long as the time expiry is not reached, the result set is obtained from the cache. Otherwise, a new connection to MySQL is established, performing a query and returning a new result set, which results in another cache generation. This process is carried out by the lines:

// 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);
}

Finally, the script is capable of directly caching results sets without major inconveniencies. Eventually, we might introduce another improvement by wrapping the above code into a function. Doing so, the overall code would hide all of the internal processing, being even more flexible and portable.

Thus, this new wrapping function, which I've denominated "readData()" (or anything you like), is defined as follows:

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;
}

Now, suppose that we want to cache a result set for 24 hours, and store it in the "cache_file.txt" cache file. We may invoke the function with these parameters and then display the data, like this:

// read data from MySQL or cache file
$options=array
('host'=>'host','user'=>'user','password'=>
'password','database'=>'
databasename','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 />';
}

Definitiely the code is much more compact and readable. However, as you can see, it maintains the benefits inherent to caching result sets. Notice that the function returns the data either from MySQL or the cache file. In this circumstance, I've chosen to display the result, but it might have been post-processed in some other way before sending it to the browser. As mentioned before, this caching method is more flexible than caching the entire HTML output.

To wrap up

In this first part of the series, I've demonstrated that building a result set caching system is a rather easy process. For developers working with a procedural approach, this solution can be used as a base structure for further improvements. However, there is still a long road in front of us.

In the second article, I'll implement a result set caching script based on a content-change caching trigger, exploring yet another nice possibility offered by this technique. So, get ready for next part!



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

blog comments powered by Disqus
   

PHP ARTICLES

- 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...
- PHP: Building Concrete Validators
- Sanitizing Input with PHP
- Executing Shell Commands with PHP
- Handling File Data with PHP
- File Security and Resources with PHP
- ArrayObject PHP Class Examples
- ArrayObject PHP Class: An Introduction
- Getting File System Data with PHP
- PHP Tools for Working with the File and Oper...
- Working with the File and Operating System w...
- PHP Proxy Patterns: Completing a Blog


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 8 - Follow our Sitemap

Dev Shed Tutorial Topics: