

All function names starting with a double underscore, like __construct(), are 'magical' for they are automatically called in certain situations. For example,
the __construct() is run automatically when a class is instantiated with the new keyword.
The magic method __toString() can be of use when you want to convert (part of an) object to a string:
The magic method __clone() can be of use when you want to clone an object. The clone object is a copy of the original object and is independently of the original. If you would just do:
$a = new MyClass;
$b = $a;
any changes to the properties of $b will also be made to $a. Only a reference to the same object is made:
To make a clone use the clone keyword: $b = clone $a;
However, if aggregation is used to, for example, associate a manufacturer with a product, cloning an object still result in a reference:
Accessing properties automatically:
The magic method __set() and __get() can be of use when you don't want to write each setter and getter method for a property individually. Control over the property is less: the value of the property is public and inspection of it is difficult:
Accessing methods automatically:
The magic method __call() is used whenever a called method does not exists in the current class:
This can be handy when using aggregation, because in this way you don't have to type each method individually (in the first __clone() example there were only two methods, but if there were twenty there would be a lot of typing involved):
The magic method __toString() can be of use when you want to convert (part of an) object to a string:
<?php
class Products{
// Properties
protected $_title;
protected $_category;
// Methods
public function getCategory(){
return $this->_category;
}
public function getTitle(){
return $this->_title;
}
}
class Order extends Products{
// Properties
protected $_price;
protected $_deliver;
// Methods
public function __construct($title, $category, $price){
$this->_title = $title;
$this->_category = $category;
$this->_price = $price;
$this->freeDomesticShipment();
}
public function getPrice(){
return $this->_title;
}
public function getDeliver(){
return $this->_deliver;
}
protected function freeDomesticShipment(){
$this->_deliver = $this->_price > 30 ? "Yes" : "No" ;
}
public function __toString(){
return $this->_title;
}
}
$order = new Order("CD Brahms", "Media", "45");
echo $order; // displays CD Brahms
?>
The magic method __clone() can be of use when you want to clone an object. The clone object is a copy of the original object and is independently of the original. If you would just do:
$a = new MyClass;
$b = $a;
any changes to the properties of $b will also be made to $a. Only a reference to the same object is made:
<?php
class A {
public $foo = 1;
}
$a = new A();
$b = $a; // $a and $b are copies of the same identifier
$b->foo = 2;
echo $a->foo."<br />"; // 2
$c = new A();
$d = &$c; // $c and $d are references
$d->foo = 2;
echo $c->foo."<br />"; // 2
?>
However, if aggregation is used to, for example, associate a manufacturer with a product, cloning an object still result in a reference:
<?php
class Manufacturer{
protected $_name;
public function setManufacturerName($name){
$this->_name = $name;
}
public function getManufacturerName(){
return $this->_name;
}
}
class Product{
protected $_title;
protected $_category;
protected $_manufacturer;
public function __construct(){
$this->_manufacturer = new Manufacturer();
}
public function getCategory(){
return $this->_category;
}
public function getTitle(){
return $this->_title;
}
public function setManufacturerName($name){
$this->_manufacturer->setManufacturerName($name);
}
/*public function __clone(){
$this->_manufacturer = clone $this->_manufacturer;
} // with use of this magic method __clone() it will echo: CD Brahms is made by Producent A */
public function getManufacturerName(){
return $this->_manufacturer->getManufacturerName();
}
}
class Order extends Product{
protected $_price;
protected $_deliver;
public function __construct($title, $category, $price){
parent::__construct();
$this->_title = $title;
$this->_category = $category;
$this->_price = $price;
$this->doWeDeliver();
}
public function setTitle($title){
$this->_title = $title;
}
public function getPrice(){
return $this->_price;
}
public function getDeliver(){
return $this->_deliver;
}
protected function doWeDeliver(){
$this->_deliver = $this->_price > 30 ? "Yes" : "No" ;
}
public function displaySentence(){
echo "Product: ".$this->_title." Category: ".$this->_category." Prijs: ".$this->_price." Gratis bezorging: ".$this->_deliver;
}
}
$order = new Order("CD Brahms", "Media", "45");
$order->setManufacturerName("Producent A");
echo $order->getTitle()." is made by ". $order->getManufacturerName()."<br />"; // CD Brahms is made by Producent A
$order2 = clone $order;
$order2->setTitle("Second title");
$order2->setManufacturerName("Producent B");
echo $order2->getTitle()." is made by ". $order2->getManufacturerName()."<br />"; // Second title is made by Producent B
echo $order->getTitle()." is made by ". $order->getManufacturerName()."<br />"; // CD Brahms is made by Producent B CD Brahms is made by Producent A with use of __clone()
?>
Accessing properties automatically:
The magic method __set() and __get() can be of use when you don't want to write each setter and getter method for a property individually. Control over the property is less: the value of the property is public and inspection of it is difficult:
<?php
class Lazy{
private $data = array(); // value of each property is public
public function __set($key, $value){
$this->data[$key] = $value;
}
public function __get($key){
if(array_key_exists($key, $this->data)) {
return $this->data[$key];
}
}
}
$lazy = new Lazy();
$lazy->a = "first value";
$lazy->b = "second value";
$lazy->c = "third value";
echo $lazy->b; // second value
?>
Accessing methods automatically:
The magic method __call() is used whenever a called method does not exists in the current class:
<?php
class Lazy{
public function __call($method, $arguments){
$arguments = implode(", ", $arguments);
echo "Call to method ".$method."() with arguments ".$arguments." failed";
}
}
$lazy = new Lazy();
$lazy->a("title", "category"); // Call to method a() with arguments title, category failed
?>
This can be handy when using aggregation, because in this way you don't have to type each method individually (in the first __clone() example there were only two methods, but if there were twenty there would be a lot of typing involved):
<?php
class Manufacturer{
protected $_name;
public function setManufacturerName($name){
$this->_name = $name;
}
public function getManufacturerName(){
return $this->_name;
}
}
class Product{
protected $_title;
protected $_category;
protected $_manufacturer;
public function __construct(){
$this->_manufacturer = new Manufacturer();
}
public function getCategory(){
return $this->_category;
}
public function getTitle(){
return $this->_title;
}
public function __clone(){
$this->_manufacturer = clone $this->_manufacturer;
}
public function __call($method, $arguments){ // replaces setManufacturerName() and getManufacturerName() wich do not exist in current class
if (method_exists($this->_manufacturer, $method)) {
return call_user_func_array(array($this->_manufacturer , $method), $arguments);
}
}
/*public function setManufacturerName($name){
$this->_manufacturer->setManufacturerName($name);
}*/
/*public function getManufacturerName(){
return $this->_manufacturer->getManufacturerName();
}*/
}
class Order extends Product{
protected $_price;
protected $_deliver;
public function __construct($title, $category, $price){
parent::__construct();
$this->_title = $title;
$this->_category = $category;
$this->_price = $price;
$this->doWeDeliver();
}
public function setTitle($title){
$this->_title = $title;
}
public function getPrice(){
return $this->_price;
}
public function getDeliver(){
return $this->_deliver;
}
protected function doWeDeliver(){
$this->_deliver = $this->_price > 30 ? "Yes" : "No" ;
}
public function displaySentence(){
echo "Product: ".$this->_title." Category: ".$this->_category." Prijs: ".$this->_price." Gratis bezorging: ".$this->_deliver;
}
}
$order = new Order("CD Brahms", "Media", "45");
$order->setManufacturerName("Producent A");
echo $order->getTitle()." is made by ". $order->getManufacturerName()."<br />"; // CD Brahms is made by Producent A
$order2 = clone $order;
$order2->setTitle("Second title");
$order2->setManufacturerName("Producent B");
echo $order2->getTitle()." is made by ". $order2->getManufacturerName()."<br />"; // Second title is made by Producent B
echo $order->getTitle()." is made by ". $order->getManufacturerName()."<br />"; // CD Brahms is made by Producent A
?>