PDA

View Full Version : [OOP] How to define a class. PART 2



Floydian
07-12-2008, 06:48 AM
Now we're going to look at adding a constructor and a destructor to our database class from PART 1 of this series.

In the database class, we had the connection settings set in the class. This is very limiting because any time the class is used, you're always connected with the same user and to the same database. And we had to call the MyDatabase::Connect method before we connected to the database. Add to that the fact that nothing closed out the database connection either.

The __construct() and __destruct() methods will perform these tasks for us exceptionally well. We'll take the Connect() method and change it's name to __construct() which will cause this function to run automatically. Then we'll add in four parameters to the __contruct(). This will allow the constructor to accept a username, password, host, and default database parameters.

Here we go!


<?php
class MyDatabase {

// Define the class properties
// Note how we can define all protected properties on one line in this example.
protected $Connection, $QueryError, $ConnectionStatus = false;

// Our constructor will connect to the database
// It will store any errors encountered along the way in the $QueryError property.
// The constructor doesn't return anything since we're creating a new object, you'd
// be overwritting your object with anything that's returned. We'll use the ConnectionStatus
// property to overcome this.
function __construct($db_host, $db_user, $db_pass, $db_schema) {
$this->Connection = mysql_connect($db_host, $db_user, $db_pass);
if($this->Connection === false) {
$this->QueryError = mysql_error();
$this->ConnectionStatus = false;
} elseif (mysql_select_db($db_schema) === false) {
$this->QueryError = mysql_error($this->Connection);
$this->ConnectionStatus = null;
} else {
$this->ConnectionStatus = true;
}
}

// This method is used to return to us the $QueryError property.
function GetError() {
return $this->QueryError;
}

// This function allows us to see and test if we're connected to the database. Additionally,
// since the value of this property can be null, a null value tells us we're connected to the database,
// but that we don't have a schema selected.
function IsConnected() {
return $this->ConnectionStatus;
}

// Our destructor closes out the connection and sets the ConnectionStatus property
// to false. Since it's possible to call the destructor while the object still exists,
// the ConnectionStatus property will allow us to know if the connection is live or not.
function __destruct() {
if ($this->ConnectionStatus !== false) {
mysql_close($this->Connection);
$this->ConnectionStatus = false;
}
}

}

$db = new MyDatabase('localhost', 'mememe', '1234abcd', 'my_game');

if ($db->IsConnected() !== true) {
echo $db->GetError();
} else {
echo "Successfully connected to the database.";
}
?>

There's quite a bit different about this new Database class. At the end of this section of code where I instantiate a new MyDatabase object, note how I pass the connection settings when making the new object. Because of this, we have the ability to connect to as many databases as we want simultaneously.

The __autoload() method automatically connects us to the the database. However, unlike the Connect() method from before, you can't return anything with a constructor. Instead of returning true or false upon success or failure, we add in a property called ConnectionStatus that will tell us if we're connected or not. Then we use the IsConnected() method to get that value and turn it into something usable outside of the class.

I hope you're starting to see how classes are defined in a way that is similar to the internal functions of php. Consider the is_numeric, is_null, is this, is that family of functions. PHP internally has properties that tells itself what data type the data is. However, to access those properties, we must use functions.

Your classes should follow this sort of methodology. I always ask myself, would the designers of PHP make functions that work this way? If the answer is no, then it's likely that my class method is not being designed the way it should be.

Remember this: you don't need to know how serialize() works internally, and you don't need to know how substr() works internally. You simply use the function and it does what it's supposed to.

If you had to open up the PHP source code which is written in C++ in order to figure out how to use a function, I think it'd be likely that you'd soon start getting tired of having to go to the trouble.

Similarly, if you have to open up your class definition and look at how it's coded in order to see how to use it, then you're probably writing a class that is not all that good.


Lastly, this class defines a destructor that closes the connection for us, if there is one alive. We can accomplish this by putting in this line:

unset($db);

And your connection is closed.

Easy? Maybe not at first, but once you get the hang of it, it can make coding go faster. Especially since something like a database class that's well written can be ported to any situation where database connectivity is needed :)