Introducing PHP classes and objects
One of the most important things you can learn in PHP is how to properly use classes.
Classes allow us to:
- Organize information logically
- Implement (and share!) old code quickly and effectively
- Avoid programming's #1 sin: code repetition
Let's take a look at the following code for accessing MySQL:
<?php
function connect($server, $user, $pass, $database) {
$link = mysql_connect($server, $user, $pass);
if (!$link) {
die("MySQL Error: " . mysql_error());
} else {
echo "Connected...";
$database = mysql_select_db($database,$link);
if (!$database) {
die("MySQL Error: " . mysql_error());
} else {
echo "Using database " . $database . "...";
}
return $link;
}
function close($link) {
mysql_close($link);
return;
}
$link = connect("phpjabbers.com","pat","password");
if ($link) {
echo "Good Job!";
close($link);
}
?>
I don't like this at all. It's too much work. See how I have to return $link, then declare $link in its actual scope? Also, what if I am making another program that wants to use these function names? Bah, so much to remember and do. Programmers are lazy. Let's see a better way to do it.
The Basics
Here's some really basic syntax for you. The "class" keyword makes the name to its right a class. Anything inside of the parentheses is a class member. Members that are variables are called properties, and its functions are called methods. The word coming before a property or method can be: public, private, or protected. This determines what is called visibility.
public - anyone can access it
private - only this class can access it protected
protected - only the class and its children (classes made from this class) can access it
The __construct function is a very special function. It is called when you instantiate the class, which means you declare a class and make an object. An object is one instance of a class stored in a variable. The __destruct function is also a very special function. It is called when you stop referring to the class, that is when nothing else accesses this class. Using this, I do not even have to tell the class to close the connection specifically. It will know to do it when I am done using it.
Something you'll find yourself using constantly when working with classes is called the "$this" pseudo-variable. This variable allows us to access the members of this class easily. $this also introduces how we access properties and methods in PHP. $objectname->methodorproperty; is the syntax. Inspect this example:
<?php
class MySQL {
protected $link;
public function __construct($server, $user, $pass, $database) {
$this->link = mysql_connect($server, $user, $pass);
if (!$this->link) {
die("MySQL Error: " . mysql_error());
} else {
echo "Connected...";
$database_ret = mysql_select_db($database, $this->link);
if (!$database_ret) {
die("MySQL Error: " . mysql_error());
} else {
echo "Using database " . $database . "...";
}
}
}
public function close() {
mysql_close($this->link);
echo "Connection closed...";
}
public function __destruct() {
$this->close();
echo "Goodbye, Cruel World!";
}
}
$some_object = new MySQL("phpjabbers.com","pat","password");
//This won't work. It is a protected property that
//can only be accessed from within the class itself.
//error message: Fatal error: Cannot access protected property MySQL::$link
echo $some_object->link;
?>
A Little Metaphor
Think of it this way. You know what a key is, right? They open doors. The idea of the key is its class, but there can be as many instances of a key as possible. For example, your house or apartment key is an object made specifically for you, but its class is still a key. Its method could be open($door), and a possible property could be $cut, or the cut of the key (what doors can it open?)
Let's expand this example some more and make it actually useful...
<?php
class MySQL {
protected $link;
protected $result;
public function __construct($server, $user, $pass, $database) {
$this->link = mysql_connect($server, $user, $pass);
if (!$this->link) {
die("MySQL Error: " . mysql_error());
} else {
echo "Connected...";
$database_ret = mysql_select_db($database, $this->link);
if (!$database_ret) {
die("MySQL Error: " . mysql_error());
} else {
echo "Using database " . $database . "...";
}
}
}
public function query() {
//I want the parameters to be of a variable length, so I'll do it this way.
$argc = func_num_args();
if ($argc < 1) {
die("Error: Not enough arguments. Arguments must be like patterned like printf.")
}
$argv = func_get_args();
$pattern = $argv[0];
unset($argv[0]);
$query = vsprintf($pattern, $argv);
//may as well clean it of bad characters now
$clean = htmlspecialchars($query);
$this->result = mysql_query($clean);
if (!$this->result) {
die("MySQL Error: " . mysql_error());
} else {
echo "Successfully queried...";
}
}
public function row() {
$row = mysql_fetch_row($this->result);
print_r($row);
}
//make this function protected, because if you close the connection too early
//you can't call the top 2 functions
//so, this function is only called by the destructor, __destruct
protected function close() {
mysql_close($this->link);
echo "Connection closed...";
}
public function __destruct() {
$this->close();
mysql_free_result($this->result);
echo "Goodbye, Cruel World!";
}
}
$some_object = new MySQL("phpjabbers.com","pat","password","database");
$some_object->query("SELECT * FROM %s WHERE id=%d", "users", 1);
$some_object->row();
?>
I added to the __destruct function the code to "free the result," that is, delete the information inside $result, as well.
Distributing the Class Easily
Now you can copy the entire class, put it in perhaps the file class.mysql.php?
To use it, you can just do this:
<?php
include_once("class.mysql.php");
$some_object = new MySQL("phpjabbers.com","pat","password","database");
$some_object->query("SELECT * FROM %s WHERE id=%d", "users", 1);
$some_object->row();
$some_object->close();
?>
That is so much neater! And best of all, lazier.
Next, we'll get into some really cool things we can do with objects, perhaps like using references or interfaces. Remember kids, whatever you do, have fun doing it!
|