Introduction

To begin with, magic methods most basically said represent functions (or better know as methods) that are executing automatically under certain circumstances. The idea is that you define their usage in the code and they are also never directly called meaning that they run regardless of any restrictions. Also I’d like to mention it here that magic methods in PHP differ significantly from their usage in other object-oriented coding under other languages. There is an exact number of those magic methods and they are:

Also, note that magic methods can only be used inside classes.

  • __construct()
  • __destruct()
  • __call()
  • __callStatic()
  • __get()
  • __set()
  • __isset()
  • __unset()
  • __sleep()
  • __wakeup()
  • __toString()
  • __invoke()
  • __set_state()
  • __clone()

How it works?

However, in this part of the series of my object-oriented programming tutorials, I’ll be going only through the main methods because frankly speaking (without any intended behavior) I don’t think most of the people here would actually use the ones that I won’t be explaining here. So let’s get started.

__get()

As I always use to begin my explanations with an example let’s take the following basic class and explain how __get() can be used within it. We have one property called data and is equal to the string ‘Keeper’.

<?php  

class Foo{  
     public $data='Keeper';  

}  
$a=new Foo();  
echo $a->data;  

?>  

We create a new instance of the class and call data. Obviously, the result will be ‘Keeper’. But what if we make a call to a property that simply does not exist in our class.

<?php  
..  

echo $a->data1;  
..  

?>  

We don’t get an error but an empty result. By using get(), we can objectify on the non-existent property that is being called. Besides that, the get() method does not output any notice or error if there isn’t such case. It is being executed only when the certain event occurs. And here is how our class would look like:

<?php  

class Foo{  
     public $data='Keeper';  

     public function __get($name) {  
           echo 'Call to '.$name.' failed. No such property.';  
     }  
}  
$a=new Foo();  
echo $a->data1;  

?>  

The method is executed automatically and the $name parameter holds the name of the property that is not existent and logically, we will get output the result:

Call to data1 failed. No such property.  

__set()

Okay. The __set() method is used when we try to append or write data to a non-existent property. So, for example, we try to add the value ‘Infamous’ to the data property after the instance. Then we just rewrite the previously defined value. Everything is running as expected.

<?php  

class Foo{  
     public $data='Keeper';  

     public function __get($name) {  
           echo 'Call to '.$name.' failed. No such property.';  
     }  
}  
$a=new Foo();  
echo $a->data1='Infamous';  

?>  

But if we try to add a property that doesn’t exist in our class and append a value to it, this is where the usage of set() method comes in handy. Normally, we won’t get any error if we haven’t used set() (same as with __get()). Here comes the time for me to add something that is probably the most important thing in this tutorial. When trying to write a property that doesn’t exist and assign a value to it, it automatically gets included dynamically in our code in run-time. That is specific for PHP alone. As I said in the beginning, magic methods differ a lot in PHP than in some other programming languages. So up to our code:

<?php  

class Foo{  
     public $data='Keeper';  

     public function __get($name) {  
           echo 'Call to '.$name.' failed. No such property.';  
     }  

     public function __set($name, $value) {  
           echo 'Trying to set '.$name.' with value '.$value;  
     }  
}  
$a=new Foo();  
$a->data1='Antagonism';  

?>  

The method accepts two parameters: $name and $value. Name becomes the name of the property itself and $value becomes its value. Pretty self-explanatory, right? set() actually prevents from including any non-existent properties in our code. So let’s see an actual usage from which we can benefit by using set().

<?php  

class Foo{  
     private $data=array();  

     public function __get($name) {  
           return $this->data[$name];  
     }  

     public function __set($name, $value) {  
           $this->data[$name]=$value;  
     }  
}  
$a=new Foo();  
$a->data1='Antagonism';  
echo $a->data1;  

?>  

So what we practically do store the property that is being included by a third-party and its value to an array. That very situation of the code is called registry as a whole because that array can be used to extract the data or append new one to it. In this case, this doesn’t break our code or cause conflicts between properties carrying the same name and so on.

__call()

_call() itself has pretty much the same functionality and usage as get() and set() but with one exception/difference. It refers to methods rather than properties (as get() and set() did).

<?php  

class Foo{  
     private $data=array();  

     public function __get($name) {  
           return $this->data[$name];  
     }  

     public function __set($name, $value) {  
           $this->data[$name]=$value;  
     }  
}  
$a=new Foo();  
$a->bar();  
echo $a->data1;  

?>  

Upon execution of this code we get an error stating that we try to access an undefined method in an object context.

Fatal error: Call to undefined method Foo::bar() in ..  

Now let’s write our magic method __call() that would take care of this issue.

<?php  

class Foo{  
     private $data=array();  

     public function __get($name) {  
           return $this->data[$name];  
     }  

     public function __set($name, $value) {  
           $this->data[$name]=$value;  
     }  

     public function __call($name, $arguments) {  
           echo $name;  
     }  
}  
$a=new Foo();  
$a->bar();  
echo $a->data1;  

?>  

That would simply return the name of the method that we are referring to, which in our case is ‘bar’. Since __call() accepts two parameters, the first one we already talked about it and the arguments one is in fact an array. To make it more clear to those who are confused, let’s dump the array, add a few parameters to the method bar and see what it has within itself.

public function __call($name, $arguments) {  
           var_dump($arguments);  
     }  

And assign the parameters to the method:

$a->bar(1,2,3);  
array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }  

__invoke()

What the __invoke() method does is allow a method in an object to be called as a function. We’ll make the casual example to explain the stuff based on it.

<?php  

class Invoke{  

     public function foo($name){  
          echo $name;  
     }  

     public function __invoke($name){  
          echo $name;  
     }  

}  

$object = new Invoke();  
$object->foo('Keeper');  

?>  

Creating the instance for the method and visualizing it returns the more than predictable result ‘Keeper’. Same goes if we use the magic method directly without calling the class.

<?php  
..  
$object->__invoke('Keeper');  

..  
?>  

Though the second way of outputting a result from the __invoke() method is not practical at all, I just wanted to introduce you to the concept of using it and that it is valid to execute the code like so. We can also achieve this with much less code like for example adding the following line:

$object('Antagonism');  

This is the actual usage of that method. As you see from the last code snippet we use the object as a function.

Conclusion

As I mentioned before this is the third part of the series I’m conducting. The material is much less in amount than the previous ones and probably the future ones that I’m going to post really soon. Magic methods themselves are pretty self-explanatory, there is nothing hard even if one just follows the documentation for their usage in a certain programming language. Thanks for reading!