#native_company# #native_desc#
#native_cta#

The New PHP 5 Features for Constructors and Destructors Page 2

By Octavia Andreea Anghel
on December 21, 2010

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:
  • The implementation of certain creation design patterns, such a Singleton and Factory
  • Building classes that are intended to be used out of the object context
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.