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:

<?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 {
            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
?>


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:

<?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->"first value";
        
$lazy->"second value";
        
$lazy->"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
?>





comments powered by Disqus