Object Interaction in PHP: Introduction to Aggregation, part 2

In this second part of his series, Alejandro Gervasio gets a little more technical with the basics of Aggregation. He begins working with a MySQL abstraction class and a useful paging class, and is starting to get into writing portable code and introducing the technique of aggregation.

This is the second part of the series “Object Interaction in PHP: Introduction to Aggregation”. Welcome back. In the first part of this series, we’ve taken a look at one of the most powerful processes involved within object interaction in PHP: Aggregation.

While seasoned developers use classes on a daily basis for development tasks, which implies directly establishing a careful planned interaction between objects, there are a wide range of programmers that maybe are just starting out to learn about the pros and cons of the object-oriented paradigm.  With this concept in mind, by developing a pair of simple classes, we’ve hopefully demonstrated that implementing aggregation in PHP is not as difficult as it seems.

Stepping back and refreshing the concepts covered in the first part, we’ve put on test our abilities as developers, creating a couple of functional classes, that is, “arrayProcessor” and “dataMailer”, making them interact each other, in order to get around quickly in the terrain of aggregation.

Certainly, this is not a condition where you can leap straight away, expecting to know it all in no time, as you probably will agree. As all things in Life, object-oriented programming takes time, but it’s really a very exciting experience. But, what has this to do with aggregation? Everything! I know that you’re getting anxious to learn more about the topic, so let’s get on finding out how we can apply this powerful technique in websites.

In this second part, we’ll get a bit more demanding about ourselves, because we’re going to implement aggregation building two of the most frequently used classes: a MySQL abstraction class and a useful paging class, in order to provide some foundations for writing portable code and introduce our desired aggregation technique. Are you ready to launch forth into the exciting world of object interaction? Let’s get started!

{mospagebreak title=Fetching data with class: the “MySQLConnector” class}

Definitively, there is much to be gained from adopting an object oriented approach to use MySQL in different projects. While we find a plenty of room on the Web for well-structured MySQL abstraction classes, such as PEAR::DB to name a frequently used one, we’ll gain a practical grounding writing our own version, even if we’re quite far from getting that level of complexity.

Anyone who has spent a few days playing around with PHP, knows how to connect to MySQL and fetch some data, using a procedural approach. Yes, probably you’ve seen this code hundreds of times:

// connect to MySQL
$db=@mysql_connect(‘host’,’username’,’password’) or die(‘Error connecting to the MySQL server’);
// select database
@mysql_select_db(‘database’,$db) or die(‘Error selecting database’);
// perform a query selecting some records
$result=mysql_query(‘SELECT * FROM table’,$db) or die(‘Error performing query’);
// display results
while($row=mysql_fetch_array($result,MYSQL_ASSOC)){
   
// code to display results
}

In the above snippet we’ve connected to the MySQL server, selected a database, performing a simple “SELECT” statement to retrieve some records, finally displaying the results. All of the process was performed using the native PHP functions, taking a procedural approximation. I’m not going to complain loudly about these lines, since I’ve found myself, many times in the past, writing this code over and over again. However, if we’re honest, this approach doesn’t scale well for larger applications, even if we go one step further wrapping up the whole script into a function. A much better solution would be developing a class, which hides all of the internal processing to connect, fetch data, process results, and so forth, focusing primarily on the data handled, rather than on the functions themselves.

Keeping that idea in mind, let’s create a class to performs all of the most common operations associated to MySQL. This newly developed class structure, which I’ve denominated “MySQLConnector”, looks like this:

class MySQLConnector {
    // data member declaration
    var $conId; // connection identifier
    var $host; // MySQL host
    var $user; // MySQL username
    var $password; // MySQL password
    var $database; // MySQL database
    var $result; // result set
    function MySQLConnecto($host,$user,$password,$database){
        // code to setup  connection parameters
        $this->connectDB();
    }
    // connect to MYSQL server and select database
    function connectDB(){
        // code to connect to the server and select database
    }
    // perform query
    function performQuery($query){
        // code to perform query
    }
    // fetch row
    function fetchRow(){
        // code to fetch a row
    }
}

The above listed class, presents a few simple methods to deal with the usual tasks, often involved when working with MySQL. The constructor takes the same parameters used in the procedural solution, that is, the host to connect $host, the username $user, the password $password, and finally the database to work with, that is $database.

A quick look at the class shows us an immediate benefit, since we’re using one single method (the constructor) for connecting to the server and select the proper database. As you remember, the procedural solution takes up two lines of code.

The rest of the methods speaks for themselves. This way, we have a “connectDB()” private method that connect to the database, then a “performQuery()” method to perform a query against the database, and lastly, a “fetchRow()” method, which retrieves a row at a time from a result set. Definitively, the methods are very understandable, don’t you think so?

{mospagebreak title=Adding Some Functionality to the Class}

Now, let’s add some functionality to the class, writing some code for the constructor, to set up the incoming parameters. So, the complete code for this method look like this:

function MySQLConnector($host,$user,$password,$database){
    // validate incoming parameters
    (!empty($host))?$this->host=$host:die(‘Host parameter not valid’);
    (!empty($user))?$this->user=$user:die(‘User parameter not valid’);
    (!empty($password))?$this->password=$password:die(‘Password parameter not valid’);
   
(!empty($database))?$this->database=$database:die(‘Database parameter not valid’);
    // connect to MySQL and select database
    $this->connectDB();
}

Up to this point, the constructor has become really very functional; it validates each parameter passed to it, assigning them as class data members. Also, notice that within it, we’re calling the private method “connectDB()”, which complements the job of the constructor. Thus, let’s go one step forth, and define it:

// connect to MYSQL server and select database
function connectDB(){
    $this->conId=@mysql_connect($this->host,$this->user,$this->password) or die(‘Error connecting to the server ‘.mysql_error());
    @mysql_select_db($this->database,$this->conId) or die(‘Error selecting database’);
}

Although this isn’t a difficult method, it does let us connect to MySQL, and select the corresponding database. Now the internal call to this method from the constructor becomes clear. See how we’re encapsulating the native PHP function inside each method? I hope you do!

Okay, there are still two methods to be defined to get the class completed. Thus, join me below for their definitions. In first place, the “performQuery() method:

// perform query
function performQuery($query){
    $this->result=@mysql_query($query,$this->conId) or die(‘Error performing query ‘.$query);
}

And secondly, the “fetchRow()” method:

// fetch row
function fetchRow(){
    return mysql_fetch_array($this->result,MYSQL_ASSOC);
}

These are my favorites, take my word for it, because they’re simple yet powerful. The first method accepts the SQL query, performs it against the selected database and ends up building a result set.

Following the explanation, the second method fetches a row at time from the result set obtained, returning the data in an associative array, where the keys correspond to the name of the fields (notice the usage of the MYSQL_ASSOC argument). Simple, huh?

Well, I think that our job for defining class methods is already done. So, let’s put the pieces together and assemble the MySQLConnector class. Here’s the full class code:

class MySQLConnector {
    var $conId; // connection identifier
    var $host; // MySQL host
    var $user; // MySQL username
    var $password; // MySQL password
    var $database; // MySQL database
    var $result; // result set
    // constructor
    function MySQLConnector($host,$user,$password,$database){
        // validate incoming parameters
        (!empty($host))?$this->host=$host:die(‘Host parameter not valid’);
        (!empty($user))?$this->user=$user:die(‘User parameter not valid’);
        (!empty($password))?$this->password=$password:die(‘Password parameter not valid’);
        (!empty($database))?$this->database=$database:die(‘Database parameter not valid’);
        // connect to MySQL and select database
        $this->connectDB();
    }
    // connect to MYSQL server and select database
    function connectDB(){
        $this->conId=@mysql_connect($this->host,$this->user,$this->password) or die(‘Error connecting to the server ‘.mysql_error());
        @mysql_select_db($this->database,$this->conId) or die(‘Error selecting database’);
    }
    // perform query
    function performQuery($query){
        $this->result=@mysql_query($query,$this->conId) or die(‘Error performing query ‘.$query);
    }
    // fetch row
    function fetchRow(){
        return mysql_fetch_array($this->result,MYSQL_ASSOC);
    }
}

So far, the class is ready to be put doing its thing, at least in simple applications. But, I’m feeling like it lacks of some frequent features, often required in such a class. What about adding a few more methods to count the total numbers or records retrieved, the number of records affected by an INSERT, UPDATE or DELETE statement, or the ID of a row just inserted? Surely, that would be a big improvement. It’s just a matter of keeping reading to find out more.

{mospagebreak title=Improving the “MySQLConnector class: adding row-counting methods}

As I said before, very often we need to count the number of rows returned by a SELECT query, in order to display paged result sets or implement another similar application. Also, it’s useful to know how many rows were affected by INSERT, UPDATE or DELETE statements. If we want to add these capabilities to our class, should we write the proper methods. Okay, the revamped version of the class looks as follows:

class MySQLConnector {
    var $conId; // connection identifier
    var $host; // MySQL host
    var $user; // MySQL username
    var $password; // MySQL password
    var $database; // MySQL database
    var $result; // result set
    // constructor
    function MySQLConnector($host,$user,$password,$database){
        // validate incoming parameters
        (!empty($host))?$this->host=$host:die(‘Host parameter not valid’);
        (!empty($user))?$this->user=$user:die(‘User parameter not valid’);
        (!empty($password))?$this->password=$password:die(‘Password parameter not valid’);
        (!empty($database))?$this->database=$database:die(‘Database parameter not valid’);
        // connect to MySQL and select database
        $this->connectDB();
    }
    // connect to MYSQL server and select database
    function connectDB(){
        $this->conId=@mysql_connect($this->host,$this->user,$this->password) or die(‘Error connecting to the server ‘.mysql_error());
        @mysql_select_db($this->database,$this->conId) or die(‘Error selecting database’);
    }
    // perform query
    function performQuery($query){
        $this->result=@mysql_query($query,$this->conId) or die(‘Error performing query ‘.$query);
    }
    // fetch row
    function fetchRow(){
        return mysql_fetch_array($this->result,MYSQL_ASSOC);
    }
    // get number of rows
    function getNumRows(){
        return mysql_num_rows($this->result);
    }
    // get number of affected rows
    function getAffectedRows(){
        return mysql_affected_rows($this->conId);
    }
    // get ID from last inserted row
    function getInsertID(){
        return mysql_insert_id($this->conId);
    }
}

At this point, we’re incorporate the “getNumRows()”, “getAffectedRows()” and “getInsertID” methods, respectively, to calculate the number of records returned after performing a SELECT statement, as well as to determine the number of records affected after an INSERT UPDATE or DELETE statement has being executed. Also, the class is able to calculate the ID (in case of havingAUTO_INCREMENT table fields) of the last row inserted in a table.

Of course, there may be more methods valid to be added to the class, but for the moment it’s more than enough. So, having completed the class definition, it’s time to look at a possible implementation. Just join me in the next example.

{mospagebreak title=Implementing the “MySQLConnector” class: a practical example}

Armed with the ready class, it’s rather simple to setup an example in order to see how it can be implemented. As you might guess, the following example shows a possible usage of the class:

// include MySQLConnector class
require_once ‘mysqlclass.php';

// instantiate a new object from MySQLConnector class
$db=&new
MySQLConnector(‘localhost’,’username’,’password’,’database’);
// build the query
$sql=’SELECT name FROM table';
// perform query
$db->performQuery($sql);
// display results
while($row=$db->fetchRow()){
    // display values from a “name” table field
    echo $row['name'].'<br />';
}

echo ‘Number total of records returned: ‘.$db->getNumRows();

From the above example, we can clearly see that connecting to MySQL, selecting a database, and displaying some results after performing a SELECT statement, is a breeze. Indeed, the code speaks by itself, simply because we really know what’s happening in each line. What’s more, the code is extremely portable for being easily plugged into another applications. What more can we ask for?

To Wrap It Up…

In this second part of the series, we’ve progressively developed a MySQL abstraction class, handy to manage database operations following an object-oriented approach. However, in order to implement aggregation in PHP, we need to have at hand another class, right? Well, in the next part we’ll build up a paging class, as the perfect complement for establishing the proper object interaction and show how aggregation can be used with these two functional classes.

Of course, as usual, feel free to use the above class to expand your own horizons in object-oriented programming and have some fun tweaking the code. See you in the next part!

[gp-comments width="770" linklove="off" ]

antalya escort bayan antalya escort bayan Antalya escort diyarbakir escort