Home arrow PHP arrow Page 4 - User-defined Interfaces in PHP 5: Introduction to Core Concepts

Making the Round Trip: defining the “MySQLCache” class - PHP

PHP5 takes users increasingly in the direction of object-oriented programming. The Standard PHP Library (SPL) is a new item that helps developers both with the creation of OOP applications and the maintenance of standardization. The SPL enables developers to work with user-defined interfaces. In this article, the first of a series, Alejandro Gervasio uses examples to introduce you to working with these interfaces, which can keep you from having to reinvent the wheel with each new project.

TABLE OF CONTENTS:
  1. User-defined Interfaces in PHP 5: Introduction to Core Concepts
  2. What are interfaces? Defining core concepts
  3. The practical side: defining the “DeSerializer interface and “PostSaver” class
  4. Making the Round Trip: defining the “MySQLCache” class
  5. A functional example: using the “MySQLCache” and “PostSaver” classes
By: Alejandro Gervasio
Rating: starstarstarstarstar / 13
December 19, 2005

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

Now that you know how to make a class implement an interface, I’m going to define the second class, “MySQLCache”, which caches MySQL results based on a time expiry trigger. Its source code is as following:

// class MySQLCache
class MySQLCache implements DeSerializer{
    private $host; // MySQL host
    private $user; // MySQL user
    private $password; // MySQL password
    private $database; // MySQL database
    private $query; // SQL query
    private $cacheFile; // cache file
    private $expiry; // expire time
    public function __construct($parameters=array()){
        if(count($parameters)<7){
            throw new Exception('Invalid number of parameters');
        }
        foreach($parameters as $parameter=>$value){
            if(!$parameter||!$value){
                throw new Exception('Invalid connection
parameters');
            }
            $this->{$parameter}=$value;
        }
    }
    // determine if cached data is valid
    private function isCacheValid(){
        if(file_exists($this->cacheFile)&&filemtime($this-
>cacheFile)>(time()-$this->expiry)){
 return true;
        }
        return false;
    }
    private function readMySQL(){
        $this->connectDB();
        return $this->query();
    }
    private function connectDB(){
        if(!$this->conID=mysql_connect($this->host,$this-
>user,$this->password,$this->database)){
            throw new Exception('Error connecting to MySQL');
        }
        if(!mysql_select_db($this->database,$this->conID)){
            throw new Exception('Error selecting database');
        }
    }
    private function query(){
        if(!$this->result=mysql_query($this->query)){
            throw new Exception('Error running query '.$this-
>query);
        }
        while($row=mysql_fetch_array($this->result)){
            $data[]=$row;
        }
        $this->data=$data;
        $this->data=$this->getSerializedData();
        $this->writeCache();
        return $data;
    }
    private function writeCache(){
        // write cache file
        if(!$fp=fopen($this->cacheFile,'w')){
            throw new Exception('Error opening cache file');
        }
        // lock cache file
        if(!flock($fp,LOCK_EX)){
 throw new Exception('Unable to lock cache file');
        }
        // write serialized data to cache file
        if(!fwrite($fp,$this->data)){
            throw new Exception('Error writing to cache file');
        }
         // unlock cache file
        flock($fp,LOCK_UN);
        fclose($fp);
    }
    // read cache file
    private function readCache(){
        if(!$this->data=file_get_contents($this->cacheFile)){
            throw new Exception('Error reading cache file');
        }
        // return cached data
 return $this->getUnserializedData();
    }
    // unserialize data
    public function getUnserializedData(){
        return unserialize($this->data);
    }
    // serialize data
    public function getSerializedData(){
        return serialize($this->data);
    }
    // read data either from MySQL or cache file
    public function getData(){
        if(!$this->isCacheValid()){
            return $this->readMySQL();
        }
        else{
            return $this->readCache();
        }
    }
}

Despite the apparently-complicated look of the class, its rationale is fairly simple. Essentially, the tasks performed by the class can be subsumed in the following sequence: first, a MySQL result set is obtained through the “query()” method, once a successful connection has been established. Then, the result set is converted to an array and serialized by the “getSerializedData()” method. Finally, the serialized data is written to a specified cache file, which will be evaluated by the “isCacheValid()” method, in order to force a new cache generation when a given time expiry has been reached.

As long as the cache is considered valid, data will be read from the given cache file. Otherwise, a new result set will be retrieved by running a SELECT statement and returned to the application as an array for further processing.

Since the class’ logic is fairly understandable, I won’t spend a long time explaining its functionality. However I’d like to strongly point out the implementation of the “DeSerializer” interface within the class. Notice that again the “getSerializedData()” and “getUnserializedData()” are specifically defined within the class, to perform the serialize-unserialize sequence on the data. Although these methods basically perform the same tasks exposed within the first class “PostSaver”, they’re implemented in a different way, as you can appreciate through the lines below:

// unserialize data
public function getUnserializedData(){
    return unserialize($this->data);
}
// serialize data
public function getSerializedData(){
    return serialize($this->data);
}

This condition is telling us that, despite the fact that both classes implement the same interface, the corresponding methods are defined differently. Therefore, the generic functionality defined through the interface is specifically implemented in different ways at class level. With reference to the example, there are two types of objects with nothing in common that use the same methods declared in the interface.

The example shows clearly the differences in using subclasses derived from the same abstract parent class, due to the mere fact that each object belongs to a different family type. Otherwise, when working with a base parent class, child objects would be of the same type. In either case, as an implementer, it’s important that you know how to spot the difference.

At this point, I have demonstrated the functionality of user-defined interfaces. However, in order to reaffirm the concepts that you just learned, I’ll write a couple of functional examples that demonstrate the usage of the previous classes. Thus, let’s get rid of the boring details and jump straight into the examples.



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