Using Directory Iterators and MySQL with Adapter Objects with PHP

If you’re a PHP programmer who’s searching for a comprehensive tutorial on how to create adapter classes with PHP 5, them look no further. Welcome to the final installment of the series “Implementing adapter objects with PHP.” Made up of two parts, this series teaches you how to implement the adapter design pattern in PHP 5, and it accompanies the corresponding theory with educational examples.

Quite possibly, you’ll remember that in the first part of the series I went through the definition and application of this design pattern, and additionally provided you with some illustrative code samples to demonstrate how the functionality of a given class can be easily expanded without using inheritance.

Now, speaking more specifically, you’ll recall that the hands-on example that I developed in the first article was focused on creating a directory adapter class. This class was originally defined for extending the functionality of another one, in this case conceived as a generic directory processor.

Of course, the best thing about building an adapter class rests on the fact that this process is entirely performed without the need to use a more conventional approach, such as applying inheritance.

However, it should be noticed that the implementation of the adapter pattern with PHP is applicable particularly in those situations where working directly with subclasses is nearly impossible, or when a certain application has been so poorly developed that the only way to tackle a specific problem is by defining a new class that conforms to a predefined model.

In all other situations, inheritance is probably the best approach to follow when the functionality of an existing class must be extended inside the context of a given application.

All right, now that I recapitulated quickly the topics covered in the first article, let me tell you what you’ll learn in this one. Provided that you understand the basic concepts of the adapter pattern, in this final tutorial, I’ll show you how to use it in conjunction with the "DirectoryIterator" class, bundled with PHP 5, and with a couple of MySQL wrappers as well.

Having established the subject of this article, let’s get started.

{mospagebreak title=Working with directory iterators and adapters together}

The first example that I plan to develop in this article is focused on creating an adapter class which will eventually expand the functionality of the popular "DirectoryIterator" class included with the SPL package. Additionally, even when this approach may not be the best one (inheritance is preferred for this specific case), it will allow me to demonstrate how to use the adapter pattern in a more useful situation.

Having clarified the above issue, take a look at the following code snippet, which defines the pair of classes that comprise the adapter entity discussed earlier:

//define abstract 'AbstractDirectoryIteratorAdapter' class

abstract class AbstractDirectoryIteratorAdapter{
    private $dirIterator;

    abstract public function getDetailedInfo();


//define concrete 'DirectoryIteratorAdapter' class

class DirectoryIteratorAdapter extends AbstractDirectoryIteratorAdapter{

   public function__construct(DirectoryIterator $dirIterator){


    public function getDetailedInfo(){

	foreach($this->dirIterator as $dirEntry){


            $info.='Last modification timestamp of current directory 
entry is :'.$dirEntry->getMTime().'<br />';             $info.='Path of current directory entry is :
'.$dirEntry->getPath().'<br />';             $info.='Type of current directory  entry is :
'.$dirEntry->getType().'<br />';             $info.='Full path of current directory entry is :
'.$dirEntry->getPathName().'<br/>';             $info.=$dirEntry->isReadable()?'Current directory entry is
readable<br />':'Current directory entry is not readable<br />';         }         return $info;              } }

If you take some time and examine the above example, you’ll realize that there are some interesting aspects worthy of highlighting here. First, notice how the constructor that corresponds to this new "DirectoryIteratorAdapter" class takes up an object of type "DirectoryIterator," which is assigned opportunely as a class property.

As you can see, the reason for doing this is really obvious. Since I’m not using inheritance in this case, the simplest way to expand the functionality of a specific class is by simply injecting the class in question straight into its adapter. That was simple, wasn’t it?

Second, the previous adapter class also exposes the "getDetailedInfo()" method, which uses three predefined methods that come with "DirectoryIterator" to expand its original functionality and provide more specific information about a given directory and its corresponding entries.

In addition, I’d like to note that I used the conventional approach for concatenating strings inside this referenced method, but you can easily change this and utilize the "heredoc" syntax, which is slightly more understandable.

At this stage, I’m pretty certain that you grasped the technique that I applied here for creating an adapter class, aimed at extending the functionality of the familiar "DirectoryIterator." However, there is still more material to learn, since I want to show you how this adapter class works with a concrete example.

Sounds really intriguing, right? Then, don’t waste any more time; read the following section.

{mospagebreak title=Putting the adapter class to work}

Naturally, I know that you want to see how the adapter class that I defined in the previous section works, therefore I prepared a concrete example that demonstrates clearly the functionality of this class.

In this case, and assuming there’s a sample "default_path" directory that contains two files named "file1.txt" and "file2.txt," here’s the corresponding code sample:

try{     $dirIteratorAdapter=new DirectoryIteratorAdapter(new
DirectoryIterator('default_path/'));     echo $dirIteratorAdapter->getDetailedInfo(); } catch(Exception $e){     echo $e->getMessage();     exit(); } /* displays the following: -------------------------------------------------------------------------- Last modification timestamp of current directory entry is : 1155050050 Path of current directory entry is : default_path Type of current directory entry is : dir Full path of current directory entry is :default_path/. Current directory entry is readable -------------------------------------------------------------------------- Last modification timestamp of current directory entry is : 1155061462 Path of current directory entry is : default_path Type of current directory entry is : dir Full path of current directory entry is :default_path/.. Current directory entry is readable -------------------------------------------------------------------------- Last modification timestamp of current directory entry is : 1149698631 Path of current directory entry is : default_path Type of current directory entry is : file Full path of current directory entry is :default_path/file1.txt Current directory entry is readable -------------------------------------------------------------------------- Last modification timestamp of current directory entry is : 1149698651 Path of current directory entry is : default_path Type of current directory entry is : file Full path of current directory entry is :default_path/file2.txt Current directory entry is readable */

As you can see, the prior example shows how the original "DirectoryIterator" class can be expanded without using inheritance. Also, with reference to the script listed above, you’ll realize that it iterates over each directory entry and displays some useful information, such as the path of each element, type, timestamp, and so forth.

So far, with the example you saw before, I think you should be equipped with a fairly decent background on how to apply the adapter pattern with PHP 5. Nevertheless, I’d like to finish this series by teaching you another case where this pattern can be applied with minor hassles: creating an adapter that expands the capacity of a MySQL result set processing class.

Want to find out how this adapter class will be created? Jump into the following section and keep reading.

{mospagebreak title=Adapting MySQL result sets}

As I expressed in the previous section, the last example that I plan to set up here concerning the implementation of the adapter pattern with PHP 5 consists basically of expanding the functionality of a MySQL result set handling class, obviously without having to appeal to the goodies of inheritance.

That being said, I listed the two base classes responsible for connecting to MySQL, running queries and so forth, as well as for handling data sets. Have a look at them, please:

// define 'MySQL' class class MySQL{     private $conId;     private $host;     private $user;     private $password;     private $database;     private $result;     public function__construct($options=array()){      if(count($options)<4) {throw new Exception('Invalid number of connection
parameters');         }         foreach($options as $parameter=>$value){             if(!$value){                 throw new Exception('Invalid parameter '.$parameter);             }    $this->{$parameter}=$value;         }         $this->connectDB();     }     // connect to MySQL     private function connectDB(){        if(!$this->conId=mysql_connect($this->host,$this->user,
$this->password)){             throw new Exception('Error connecting to the server');         }      if(!mysql_select_db($this->database,$this->conId)){             throw new Exception('Error selecting database');         }     }     // run query     public function query($query){         if(!$this->result=mysql_query($query,$this->conId)){             throw new Exception('Error performing query '.$query);         }         return new Result($this,$this->result);     } } // define 'Result' class class Result {     private $mysql;     private $result;     public function__construct(&$mysql,$result){       $this->mysql=&$mysql; $this->result=$result;     }     // fetch database table rows     public function fetchRow(){         return mysql_fetch_assoc($this->result);     }     // count database table rows     public function countRows(){         if(!$rows=mysql_num_rows($this->result)){             throw new Exception('Error counting rows');         }         return $rows;     }     // count affected rows     public function countAffectedRows(){         if(!$rows=mysql_affected_rows($this->mysql->conId)){             throw new Exception('Error counting affected rows');         }         return $rows;     }     // obtain last insertion ID     public function getInsertID(){        if(!$id=mysql_insert_id($this->mysql->conId)){             throw new Exception('Error getting ID');         }         return $id;     }     // seek row     public function seekRow($row=0){    if(!int($row)||$row<0){             throw newException('Invalid result set offset');         }   if(!mysql_data_seek($this->result,$row)){             throw new Exception('Error seeking data');         }     } }

After examining the above two classes, you’ll probably find them familiar, since I used them in some of my previous PHP articles. However, this time I want you pay attention to the respective "Result" class, because I’ll use it as the starting point for extending its functionality via an adapter class.

Now, say you want to provide this class with the ability to return completely-formatted result sets, but as I said before, without deriving a subclass from it. Of course, if you learned something from the examples that I showed previously, then you’ll have the right answer for doing this: an adapter class!

Precisely, based on this premise, below I defined an adapter class that extends the capacity of the original "Result" and is able to display entirely formatted data sets. The signature for this class is the following:

// define 'ResultAdapter' class class ResultAdapter{     private $resultObj;     public function__construct(Result $resultObj){   $this->resultObj=$resultObj;     }     // get formatted result set     public function fetchFormattedResult($fieldDelimiter=' ',
$closeTag='</p>'){         $output='';         $opentag=str_replace('/','',$endTag);        while($row=$this->resultObj->fetchRow()){             $tempOutput='';             foreach($row as $data){                  $tempOutput.=$fieldDelimiter.$data;             }           $output.=$openTag.$tempOutput.$closeTag;         }       unset($openTag,$closeTag);         return $output;     } }

As you can see, the above defined adapter class certainly isn’t rocket science at all. All I did here was pass in the original "Result" object to the corresponding constructor and create a specific "fetchFormattedResult()" method to provide data sets with a certain look and feel.

One possible implementation of the prior result set adapter class can be appreciated by examining the following script:


try{     // connect to MySQL     $db=new MySQL(array('host'=>'host','user'=>'user',
'password'=>'password','database'=>'database'));     // get result set object    $result=$db->query('SELECT * FROM users');     // instantiate 'ResultAdapter' object     $resultAdapter=new ResultAdapter($result);     // display formatted result set     echo $resultAdapter->fetchFormattedResult();     /*     displays the following data wrapped up into paragraphs:     1 user1     2 user2     3 user3     4 user4     5 user5     6 user6     7 user7     8 user8     9 user9     10 user10     */ } catch(Exception $e){     echo $e->getMessage();     exit(); }


Concerning the above example, all the rows contained in the sample "USERS" database table have been displayed inside paragraphs, via the corresponding "fetchFormattedResult()" method that belongs to the previous "ResultAdapter" class.

Here, it’s clear to see how easy it is to create an adapter class without using inheritance. Of course, feel free to tweak the code of all the examples that I provided here, thus you can experiment with introducing your own modifications.

Final thoughts

Finally, we’ve come to the end of this series. In these two articles, I gave you some handy pointers on how to create adapter classes with PHP 5, in case you can’t use inheritance as the approach for extending the functionality of a given class.

As I explained in these tutorials, the adapter pattern is more suitable to apply in situations where it’s not only necessary to expand the capacity of a class, but the class must also fit the requirements of a third object.  As usual, see you in the next PHP series!

Google+ Comments

Google+ Comments