As you probably know, the new OOP features in PHP 5 bring a new perspective to PHP applications. In this article, you will see the new PHP 5 features regarding constructors and destructors, which are one of the most important aspects in any type of object-orientated class. As a reminder, a constructor is a special function of a class that is automatically executed whenever an object of a class gets instantiated. A destructor is a special function of a class that is automatically executed whenever an object should be destroyed.
The article starts with a short overview of PHP 5 constructors, compared with the old fashion PHP 4. It continues with an explanation of writing constructors with or without parameters, restrictive constructors, overloading and PHP 5 destructors. At the end, you will be able to write almost any kind of constructor for your PHP 5 classes.

PHP 5 vs. PHP 4 Constructors

As a developer, each time you try to learn something new (a technology, a design pattern, a paradigm, etc.) you start by looking at what you used in the past and trying to identify the advantages of the new concept. This approach can tell you if using PHP 5 constructors is worth your time. To that end, consider the following comparison that explores why PHP 5 constructors are superior to PHP 4:
Here are some important notes regarding constructors and destructors from the PHP documentation:

Your First PHP 5 Constructor

Let's start with a basic example of a PHP 5 constructor with no arguments. Its job will be to create an instance of its class and to initialize a set of class properties. Look through the code to get a first impression of what is happening.
<?php
class Player {
private $name;
private $surname;
private $country;
private $atp;
//this is a simple PHP 5 constructor
public function __construct() {
$this->name = "empty";
$this->surname = "empty";
$this->country = "empty";
$this->atp = 0;
}
public function setDetails($name, $surname, $country, $atp) {
$this->name = $name;
$this->surname = $surname;
$this->country = $country;
$this->atp = $atp;
}
public function displayDetails() {
echo "Name : " . $this->name . " Surname: " .
$this->surname . " Country: " . $this->country .
" Atp Ranking: " . $this->atp . "<br />";
}
}
$player_1 = new Player();
$player_1->displayDetails();
$player_1->setDetails("Rafael", "Nadal", "ESP", 1);
$player_1->displayDetails();
?>
The bolded code represents the PHP 5 unified constructor. The constructor's body initializes the four class properties with default values, while the desired values are passed to the setDetails function. Notice the use of the $this keyword to indicate that you will initialize the class properties, not local properties.
The output of this class is shown in Figure 1 below.


Click here for larger image

Figure 1. Output of Player Class (Constructor with No Arguments)

Writing a PHP 5 Constructor with Parameters

Usually, the desired values are set inside the constructor, which is much closer to the real cases. When you create a class instance, you also set the object's properties. The code below is similar to the one above; the only difference being that you eliminate the setDetails method and pass its behavior to the unified constructor:
<?php
class Player {
private $name;
private $surname;
private $country;
private $atp;
//this is a constructor with parameters
public function __construct($name, $surname, $country, $atp) {
$this->name = $name;
$this->surname = $surname;
$this->country = $country;
$this->atp = $atp;
}
public function displayDetails() {
echo "Name : " . $this->name . " Surname: " .
$this->surname . " Country: " . $this->country .
" Atp Ranking: " . $this->atp . "<br />";
}
}
$player_1 = new Player("Rafael", "Nadal", "ESP", 1);
$player_1->displayDetails();
$player_2 = new Player("Roger", "Federer", "SUI", 2);
$player_2->displayDetails();
?>
This kind of constructor is the most common in real applications. It receives a set of parameters -- which have the same names as the class properties -- and uses the $this keyword to associate each class property to the proper parameter.
The output of this class is shown in Figure 2 below.


Click here for larger image

Figure 2. Output of Player Class (Constructor with Parameters)

Your First PHP 5 Destructor

If the constructor is responsible for creating objects, the destructor is responsible for destroying objects. The destructor provides an elegant way for accomplishing necessary cleanup operations such as unsetting internal class objects, closing database connections or socket connections, etc. The destructor is automatically called when an object should be destroyed. An object of a class is destroyed when:
The destructor below calls the unset method with the class property passed as an argument:
<?php
class Player {
private $name;
private $surname;
private $country;
private $atp;
public function __construct($name, $surname, $country, $atp) {
$this->name = $name;
$this->surname = $surname;
$this->country = $country;
$this->atp = $atp;
}
public function displayDetails() {
echo "Name : " . $this->name . " Surname: " . $this->surname . "
Country: " . $this->country . " Atp Ranking: " . $this->atp . "<br />";
}
public function __destruct() {
unset($this->name);
unset($this->surname);
unset($this->country);
unset($this->atp);
echo("
Object destroyed ...");
} } $player_1 = new Player("Rafael", "Nadal", "ESP", 1); $player_1->displayDetails(); $player_2 = new Player("Roger", "Federer", "SUI", 2); $player_2->displayDetails(); ?>
The output of this class is shown in Figure 3 below.


Click here for larger image

Figure 3. Output of Player Class (Destructor)
Here are some important notes regarding destructors from the PHP documentation:

Introducing PHP 5 Restrictive Constructors

Restrictive constructors sound complex, but they actually are simple. A restrictive constructor is nothing but a regular constructor method whose level of visibility is protected or private. This function can be necessary in several cases, but two of the best known are:
Per example, a constructor for a Singleton class should be defined as below (as private, in this case):
//Locked down the constructor, therefore the class cannot be externally instantiated
private function __construct() { }
While this constructor is locked, the class supports a single instance through a method like this:
//A static member variable representing the class instance
private static $_instance = null;
public static function getInstance()
{
//or if(is_null(self::$_instance)) or if(self::$_instance == null)
if(!is_object(self::$_instance))
self::$_instance = new self;
//or, in PHP 5.3.0 or newer
//if (empty(static::$_instance)) {
// $class = get_called_class();
// static::$_instance = new $class;
//}
return self::$_instance;
}
If you are not familiar with the Singleton design pattern, read the article Implementing the Singleton Pattern in PHP 5 for instructions.

PHP 5 Constructor Overloading

Overloading constructors is a common task usually implemented as multiple constructors with the same name as the class but with different numbers/types of arguments. This is not possible with PHP 5 because it does not support constructor overloading. However, you can improvise using the __call method.
For those who are not familiar with the PHP 5 _call method, suppose that in a case of method overloading, the code defines a method that acts as a wildcard for calls to undefined methods of the corresponding class. This wildcard method will be called only when the class does not contain the method you are trying to access. Using the magic of __call() you can develop the following code:
<?php
class Player {
private $name;
private $surname;
private $country;
private $atp;
public function __construct() {
$num = func_num_args();
$args = func_get_args();
switch($num){
case 0:
$this->__call('__construct_0', null);
break;
case 1:
$this->__call('__construct_1', $args);
break;
case 2:
$this->__call('__construct_2', $args);
break;
case 3:
$this->__call('__construct_3', $args);
break;
case 4:
$this->__call('__construct_4', $args);
break;
default:
throw new Exception();
}
}
public function __construct_0(){
echo "constructor 0" . "<br />";
}
public function __construct_1($name){
$this->name = $name;
echo "constructor 1: " . $this->name . "<br />";
}
public function __construct_2($name, $surname){
$this->name = $name;
$this->surname = $surname;
echo "constructor 2: " . $this->name . "|" . $this->surname . "<br />";
}
public function __construct_3($name, $surname, $country){
$this->name = $name;
$this->surname = $surname;
$this->country = $country;
echo "constructor 3: " . $this->name . "|" . $this->surname .
"|" . $this->country . "<br />";
}
public function __construct_4($name, $surname, $country, $atp){
$this->name = $name;
$this->surname = $surname;
$this->country = $country;
$this->atp = $atp;
echo "constructor 4: " . $this->name . "|" . $this->surname . "|" .
$this->country . "|" . $this->atp . "<br />";
}

private function __call($con, $arg){
return call_user_func_array(array($this, $con), $arg);
}
}
$player_1 = new Player("Rafael");
$player_2 = new Player("Rafael", "Nadal");
$player_3 = new Player("Rafael", "Nadal", "ESP");
$player_4 = new Player("Rafael", "Nadal", "ESP", "1");
?>
Well, you have several interesting things here. The application starts when an instance of the Player class is created (this code flow is the same for each of the four instances) and ends when the instance properties are set to the passed values. When the instance is created, the __construct() constructor is called. This constructor is called no matter how many arguments you pass to it as the start point for creating a new instance. This constructor acts as a generic one, and is responsible for dispatching the initialization phase of the new object to four methods, named __construct_number_of_arguments().
To accomplish dispatching, the constructor needs the magic __call() method, which gets two arguments. The first argument is the name of the original method (in some cases this can be an unfound method but in this case). The second one is a one-dimensional, numerically indexed array containing all of the arguments for the original method.
Calling a defined/undefined method with two arguments, Rafael and Nadal, will result in the following array:
Array
(
[0] => Rafael
[1] => Nadal
)
Next, the __call() method will call the original method and pass the set of arguments.
At this point, the flow of execution is in the fake overloaded constructor, depending on the number of arguments. From here, trivial code initializes the new object properties and prints out a checking message. This message should be deleted and getter and setter methods should be used instead.
The output of this class is shown in Figure 4 below.


Click here for larger image

Figure 4. Output of Player Class (Constructor Overloading)

Conclusion

In this article, you have explored the most important aspects of the new constructor/destructor mechanism available with PHP 5's new OOP features. You saw how to write simple constructors/destructors and restrictive constructors, and how to simulate the overloading mechanism, which is not available in PHP 5 -- yet.

About the Author

Octavia Andreea Anghel is a senior PHP developer currently working as a primary trainer for programming teams that participate at national and international software-development contests. She consults on developing educational projects at a national level. She is a coauthor of the book "XML Technologies: XML in Java" (Albastra, ISBN 978-973-650-210-1), for which she wrote the XML portions. In addition to PHP and XML, she's interested in software architecture, web services, UML, and high-performance unit tests. to e-mail her.