Home arrow PHP arrow Page 3 - Caching Result Sets in PHP: The Barebones of a Caching Class

The object-oriented solution: developing a result set caching class - PHP

While procedural caching may be well-suited for small and even medium-sized applications, the picture changes for large projects. That's when object-oriented approaches come into their own. This article focuses on developing an object-based extensible caching solution.

TABLE OF CONTENTS:
  1. Caching Result Sets in PHP: The Barebones of a Caching Class
  2. Chaining things along: a quick look at the procedural caching solution
  3. The object-oriented solution: developing a result set caching class
  4. Caching with class: a deeper look at the “Cache” class
  5. More class methods in detail: ending up the round
By: Alejandro Gervasio
Rating: starstarstarstarstar / 7
October 10, 2005

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

Prior to developing the caching class, we need to specify some important prerequisites. First, the class will implement a time expiry-based caching trigger. However, this is not a big limitation, since a different caching trigger might be developed without making significant changes to the source code. This will be left as a possible additional feature.

Second, the class will aggregate a MySQL abstraction object, for having database connectivity within its scope, so if you’re not familiar with the concept of aggregation, feel free to visit Object Interaction in PHP Introduction to
Aggregation part 1
, where I’ve written an article series that discusses the topic in detail.

Finally, since the source code is highly portable, in a future article the whole set of classes will be updated to PHP 5, aimed specifically at those developers working with the latest version of PHP.

All right, having stated these few disclaimers, it’s time to look at the result caching class, which, not surprisingly, I’ve called “Cache.” Its definition is as follows:

class Cache{
            var $mysql;  // instance of MySQL object
            var $result; // instance of Result object
            var $expiry; // cache expire time in seconds
            var $cacheFile; // cache file
            var $data; // result set array
            // constructor
            function Cache(&$mysql,$expiry=86400,$cacheFile='default_cache.txt'){
                        $this->mysql=&$mysql;
                        (is_int($expiry)&&$expiry>0)?$this->expiry=$expiry:$this->mysql-
>isError('Expire time must be a positive integer');
                        $this->cacheFile=$cacheFile;
                        $this->data=array();
            }
            // if cache is valid, perform query and return a result set. Otherwise, get
results from cache file
            function query($query){
                        // check if query starts with SELECT
                        if(!preg_match("/^SELECT/",$query)){
                                   $this->mysql->isError('Invalid query. Must start with
SELECT');
                        }
                        if(!$this->isValid()){
                                   // read data from MySQL
                                   $this->result=$this->mysql->query($query);
                                   // write data to cache file
                                   $this->data=$this->write();
                        }
                        else {
                                   // read data from cache file
                                   $this->data=$this->read();
                        }
            }
            // write cache file
            function write(){
                        if(!$fp=fopen($this->cacheFile,'w')){
                                   $this->mysql->isError('Error opening cache file');
                        }
                        if(!flock($fp,LOCK_EX)){
                                   $this->mysql->isError('Unable to lock cache file');
                        }
                        while($row=$this->result->fetchRow()){
                                   $content[]=$row;
                        }
                        if(!fwrite($fp,serialize($content))){
                                   $this->mysql->isError('Error writing to cache file');
                        }
                        flock($fp,LOCK_UN);
                        fclose($fp);
                        unset($fp,$row);
                        return $content;
            }
            // read cache file
            function read(){
                        if(!$content=unserialize(file_get_contents($this->cacheFile))){
                                   $this->mysql->isError('Error reading from cache file');
                        }
                        return $content;
            }
            // determine cache validity based on a time expiry trigger
            function isValid(){
                        if(file_exists($this->cacheFile)&&filemtime($this->cacheFile)>(time
()-$this->expiry)){
                                   return true;
                        }
                        return false;
            }
            // fetch cache row
            function fetchRow(){
                        if(!$row=current($this->data)){
                                   return false;
                        }
                        next($this->data);
                        return $row;
            }
            // fetch all cache rows
            function fetchAll(){
                        if(count($this->data)<1){
                                   $this->mysql->isError('Error accessing cache data');
                        }
                        return $this->data;
            }
            // count cache rows
            function countRows(){
                        if(!$rows=count($this->data)){
                                   $this->mysql->isError('Error counting cache rows');
                        }
                        return $rows;
            }
}

At first glance, and looking at the data member declaration, we can see that the “Cache” class aggregates a MySQL object and a “Result” object, where the first one is directly passed to the constructor. So, if you might want to see the complete code for each class involved, don’t feel concerned about this. We’ll see in turn, the proper definition for all of the additional classes that we’re working with.

For the moment, let’s focus our attention on the code for the “Cache” class, which will be explained in detail over the next few lines.



 
 
>>> 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: