Using Visitor Objects with MySQL Data Sets in PHP 5

If you’re looking for brand new material to help you expand your background in using design patterns with PHP 5, then hopefully this article will suit your needs. Welcome to the final installment of the series “Introducing Visitor Objects in PHP 5.” Composed of three chapters, this series walks you through the key points of creating and using visitor objects with PHP 5, and teaches you how to use them in the context of real-world applications.

Introduction

As you hopefully learned over the course of the two previous articles, building visitor classes is not only a fairly comprehensive process that can be done without much trouble, but it’s also an exciting  experience, which indeed deserves an in-depth look. That’s why in the first article, aside from introducing the fundamentals of visitor objects, I showed you an introductory example, which demonstrated how a specific object, in this case called “the visited one” can accept another (the visitor) to allow the inspection of its properties.

In addition to the introductory example that I mentioned before, in the second tutorial I went through the development of a slightly more complex example. It illustrated how a highly generic “User” class could be inspected by its corresponding visitor, which resulted in the ability to access of all its visible properties without having to specifically use its own methods.

So far, implementing visitor objects with PHP is indeed a educational process, which helps to extend even more the boundaries of the vast arena of pattern-based programming. Based on this premise, in the course of this last article, I’ll expand the application of the visitor pattern by developing a slightly more realistic example. It will show you how to use visitors objects to establish a direct relationship between a MySQL processing class and a pagination mechanism.

In return for all the code samples that you’ll learn in this tutorial, you’ll be equipped with a better grounding, not only with reference to this pattern in particular, but also regarding the main pillars of pattern-based web development. Thus, I think it’s time to get rid of the preliminaries, and continue learning more about using visitor objects with PHP 5. Let’s move on!

{mospagebreak title=Visiting database result sets: establishing an interaction between visitors and MySQL}

In order to set up the foundations of the hands-on example that I plan to create, first I’ll define two concrete MySQL-related classes. These will allow me to establish a direct interaction between disparate MySQL data sets and the way that they will be displayed as chunked packets on a web document.

Considering this concept, below you’ll find the complete listing of the two MySQL processing classes that I mentioned before. Please, have a look at them:

// define ‘MySQL’ class
class MySQL{
    private $conId;
    private $host;
    private $user;
    private $password;
    private $database;
    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 server
    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 row
    public function fetchRow(){
        return mysql_fetch_assoc($this->result);
    }
    // count 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;
    }
    // get insert 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 new Exception(‘Invalid result set offset’);
        }
        if(!mysql_data_seek($this->result,$row)){
            throw new Exception(‘Error seeking data’);
        }
    }
    // accept visitor
    public function acceptVisitor(Visitor $visitor){
        $visitor->visitMySQLResult($this);
    }
}

As shown above, the first class is simply tasked with handling all the processes required to connect to the MySQL server and run the corresponding queries. Because these features don’t bear much discussion here, I suggest you put them from your mind for a moment and turn your attention to the second class.

Particularly, the “Result” class is a bit more interesting, since it exposes a set of understandable methods aimed at processing MySQL result sets. So far, it’s nothing unexpected, right? However, beside the respective methods, handy for counting and seeking rows, finding insertion IDs and so forth, this class presents the following method:

public function acceptVisitor(Visitor $visitor){
    $visitor->visitMySQLResult($this);
}

Now, with the introduction of the method shown above, certainly things get much more interesting. Notice how the “Result” class in question accepts a visitor object, which will be responsible for inspecting some of the properties of this class. On this occasion, and certainly at the risk of being repetitive (I mentioned this concept in the two preceding articles), you should pay strong attention to the way the “acceptVisitor()” method has been defined.

As you can see, this method accepts a visitor object as the unique input argument, and passes an instance of the “Result” class to the visitor itself via its “visitMySQLResult()” method. When working with visitor objects in PHP, you’ll probably see this schema implemented in all cases, thus keep it in mind for further reference.

Fine, now that you’ve already seen how the “Result” class listed above is provided with the ability for inputting a visitor object, it’s time to leap forward and learn how the corresponding visitor class can be created. Are you still with me? Great, now please read the following section to find out how this will be achieved.

{mospagebreak title=Revealing the anatomy of a visitor class: creating visitor objects}

As you learned in the previous section, building a MySQL result processing class capable of accepting a visitor object is in fact a straightforward process. Nevertheless, the structure of the visitor class itself hasn’t been defined yet. Thus, considering this condition, it’s very convenient to start modeling its general signature.

But how will this be done? That’s a simple question to answer. First I’ll define an abstract visitor class, and then I’ll derive a subclass from it, which will implement concretely the corresponding methods.

Therefore, here is the base abstract class that defines the general structure of visitor objects:

// define abstract ‘Visitor’ class
abstract class Visitor{
    abstract function visitMySQLResult(Result $resultObj);
}

As you can appreciate, the above abstract class has only one relevant method, that is “visitMySQLResult()”, which defines the generic behavior of the class in question. However, it should be noticed how this method accepts an object of type “Result” as its unique incoming argument, in order to do its business.

Since the previous “Visitor” base class shouldn’t present big difficulties with understanding its structure, now let me show you the respective subclass that will be provided with the concrete ability to inspect MySQL result sets. Please, take a look at the signature of this new child class:

// define subclass ‘MySQLResultVisitor’
class MySQLResultVisitor extends Visitor{
    private $resultObj;
    public function visitMySQLResult(Result $resultObj){
        return $resultObj->countRows();
    }
}

Now you’ll have to agree with me that the previous sub class is highly comprehensive. After all, its whole functionality is based simply on taking a result object as incoming parameter, and returning the number of rows present in the record set by using its “countRows()” method. True to form, this visitor in particular isn’t very demanding with reference to its visited objects, but it shows in a clear fashion how the visitor pattern can be applied in this specific situation. This isn’t rocket science at all!

Fine, at this stage you hopefully learned how a MySQL processing class can be coded in such a way that it can accept a visitor object. In addition, you also saw how the proper visitor class was defined. So, the question that comes now is: what’s the next step?

Well, as I expressed right at the beginning of this article, my intention was to create a visitor object which will be capable of establishing an interaction between several MySQL result sets and a PHP-based pagination system. Based on that prerequisite, in the following section I’ll create a comprehensive pagination class which will use a single visitor object to paginate the pertinent MySQL data sets.

To find out how this process will be done, please click on the link below and keep reading.

{mospagebreak title=Completing the round trip: defining the structure of a pagination class}

As I said in the section that you just read, the primary purpose of creating a visitor class was defining a model of interaction between the prior “Result” class and a data set pagination system. Obviously, this last component remains undefined as yet. Below I have listed the source code of a pagination class which I have been using frequently when I developed a series of articles aimed at discussing the pagination of result sets with PHP.

Here is how this pagination class looks:

// define ‘Pager’ class
class Pager{
    private $db;
    private $query;
    private $numRecs;
    private $output=”;
    public function __construct($db,$query,$numRecs=10){
        // validate query
        if(!preg_match(“/^SELECT/”,$query)){
            throw new Exception(‘Invalid query. Must begin with
SELECT’);
        }
        $this->query=$query;
        // validate number of records per page
        if(!is_int($numRecs)||$numRecs<0){
            throw new Exception(‘Invalid number of records’);
        }
        $this->numRecs=$numRecs;
        $this->db=$db;
    }
    public function displayRecords($page){
        // use visitor for obtaining number of rows in result set
        $resultObj=$this->db->query($this->query);
        $mysqlResultVisitor=new MySQLResultVisitor;
        $resultObj->acceptVisitor($mysqlResultVisitor);
        // calculate total number of records via Visitor object
        $totalRecs=$mysqlResultVisitor->visitMySQLResult
($resultObj);
        // calculate number of pages
        $numPages=ceil($totalRecs/$this->numRecs);
        if(!preg_match(“/^d{1,2}$/”,$page)
||$page<1||$page>$numPages){
            $page=1;
        }
        // get result set
        $resultObj=$this->db->query($this->query.’ LIMIT ‘.
($page-1)*$this->numRecs.’,’.$this->numRecs);
        while($row=$resultObj->fetchRow()){
            foreach($row as $key=>$value){
                $this->output.=$value.’ ‘;
            }
            $this->output.='<br />';
        }
        // create page links
        $this->output.='<div>';
        // create previous link
        if($page>1){
            $this->output.='<a href=”‘.$_SERVER['PHP_SELF'].’?
page=’.($page-1).'”>&lt;&lt;Previous</a>&nbsp;';
        }
        // create numerated links
        for($i=1;$i<=$numPages;$i++){
            ($i!=$page)?$this->output.='<a href=”‘.$_SERVER
['PHP_SELF'].’?page=’.$i.'”>’.$i.'</a>&nbsp;':$this-
>output.=$i.’&nbsp;';
        }
        // create next link
        if($page<$numPages){
            $this->output.=’&nbsp;<a href=”‘.$_SERVER
['PHP_SELF'].’?page=’.($page+1).'”>Next&gt;&gt;</a>';
        }
        $this->output.='</div>';
        // return final output
        return $this->output;
    }
}

Certainly, I’m not going to discuss the logic of the class listed above, simply because it’s out of the scope of this article. But it’s clear to see that this class is capable of displaying paginated record sets returned by MySQL, in addition to including the so-called “page links.”

Now, once you have a good idea of how this paging class works, please have a look at the following fragment of code, excerpted from its “displayRecords()” method:

// use visitor for obtaining number of rows in result set
$resultObj=$this->db->query($this->query);
$mysqlResultVisitor=new MySQLResultVisitor;
$resultObj->acceptVisitor($mysqlResultVisitor);
// calculate total number of records via Visitor object
$totalRecs=$mysqlResultVisitor->visitMySQLResult($resultObj);

Here’s where the real action takes place! If you examine the above code snippet, you’ll realize that this “Pager” class uses the mentioned visitor object to determine the number of rows returned by a SELECT query, and based on this parameter, it displays chunks of database records.

In other words, the visitor in question inspects the previous “Result” class, and retrieves one of the values required for the pagination system to display paginated results. At this stage, the link established between the classes that process data sets and paginate them respectively should be clear to you.

Okay, having defined all the classes required to implement a comprehensive pagination system, allow me to put all the pieces together. The code listing below shows precisely how all the classes fit each other, after populating a sample “users” database table with some trivial data:

try{
    // connect to MySQL
    $db=new MySQL(array(‘host’=>’host’,’user’=>’user’,
‘password’=>’password’,’database’=>’database’));
    // paginate result set
    $pager=new Pager($db,’SELECT * FROM users’,$numRecs=2);
    // display paged result set
    echo $pager->displayRecords($_GET['page']);
}
catch(Exception $e){
    echo $e->getMessage();
    exit();
}

And finally, the output of the previous script is depicted by the following screen shot:

Final thoughts

That covers the topic of using visitors for now. Over this series, I introduced in a friendly fashion the creation and usage of visitor objects in PHP 5. From basic examples of how to utilize these objects, to including them in more complex applications, the learning experience has been hopefully educational.

Either if you’re just starting to enter the arena of pattern-based programming or only refreshing some of its more relevant concepts, I hope this article has been helpful to you.  See you in the next PHP tutorial!

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan