What are PHP Magic Methods?
PHP Magic methods are a specialized method that is executed in response to a specific event. Each magic methods start with two underscores(__) and it is called automatically when a certain condition is met. It triggers custom behaviors defined by a programmer inside the class. Some of the magic methods are __construct(), __destruct(), __toString(), __get(), __set(), __call() etc.
In this tutorial, we are going to explore php magic methods.
Constructors and Destructors
Constructors (__construct) is the most common magic methods. Constructors and Destructors are called when an object is created and destroyed.
__construct
The __construct() method is called when an object of a class is created. It is the first method which is called when an object of a class is created.
A Constructor is used for any initialization that the object may need before it is used.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Class Student { private $age; //constructor public function __construct($age) { $this->age = $age; } public function getAge() { echo $this->age; } } //constructor is called and assign age 18 $Jhon = new Student(18); $Jhon->getAge(); //18 |
In above example, we are creating an instance of the Student class and passing a parameter(value of age) that will be injected into the __construct() method. We don’t have to call __construct() method it will be automatically called when an instance of a student class is created.
How to call a parent constructor in PHP
__destruct
The __destruct() method is called when an object of a class is destroyed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Class Student { private $age; public function __construct($age) { $this->age = $age; } public function getAge() { echo $this->age; } public function __destruct() { echo "Destructor is called"; } } $Jhon = new Student(18); //Destructor is called unset($Jhon); |
The __destruct() method will be useful for any cleanup operations after an object is destroyed. Like __construct() method it’s also called automatically. The lifecycle of a PHP request is very short, so it is rare to find the use of a __destruct() method in our codebase.
__get() Magic Method
The __get() method is called when the object of a class try to read a property that is inaccessible or unavailable.
Inaccessible means either the property is not defined or it is not public.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Class Student { private $age; private $name; public function __construct($age, $name) { $this->age = $age; $this->name = $name; } public function getAge() { echo $this->age; } } //instance of student class $student = new Student(18, "John"); //Try to access private property echo $student->name; //Fatal error: Cannot access private property Student::$name |
In the above code, we are trying to access private property outside the class which leads to a fatal error. Let’s modify the code and use __get() method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Class Student { private $age; private $name; public function __construct($age, $name) { $this->age = $age; $this->name = $name; } public function getAge() { echo $this->age; } public function __get($name) { if(property_exists($this, $name)) { return $this->$name; } } } $student = new Student(18, "John"); //__get magic method is called echo $student->name; //print John |
Take another example, In this code, we are trying to echo a property which doesn’t exist.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Class Student { private $age; private $name; public function __construct($age, $name) { $this->age = $age; $this->name = $name; } public function getAge() { echo $this->age; } public function __get($name) { if(property_exists($this, $name)) { return $this->$name; } } } $student = new Student(18, "John"); /* * __get magic method is called as address property doesn't exists */ echo $student->address; |
__set() Magic Method
The __set() method is called when code tries to set a method that is not accessible or doesn’t exist.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Class Student { private $age; private $name; public function __construct($age, $name) { $this->age = $age; $this->name = $name; } public function getAge() { echo $this->age; } public function __set($property, $value) { $this->$property = $value; } } $student = new Student(18, "John"); /* * __set magic method */ $student->address = "India"; echo $student->address; |
The __get() and __set() method is not a substitutes for getters and setters. They just allow you to handle method class or property access that would otherwise result in an error. As compared to proper getter and setters they are considerably slower.
__isset() Magic Method
The __isset() method is called when isset() or empty() check non-existent or inaccessible class property.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Class Student { private $age; private $name; public function __construct($age, $name) { $this->age = $age; $this->name = $name; } public function __isset($name) { echo "Non-existent property $name"; } } $student = new Student(18, "John"); /*calling non-existent property address *__isset() magic method is triggered */ isset($student->address); |
NOTE – isset() is a language construct whereas __isset() is a magic method.
Difference between isset() and __isset()
__call() Magic Method
The __call() method is called when the method of a class does not exist or inaccessible.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Class Student { private $age; private $name; public function __construct($age, $name) { $this->age = $age; $this->name = $name; } public function getAge() { echo $this->age; } public function __call($name, $arguments) { echo $name." Doesn't exists"; } } $student = new Student(18, "John"); /* * getAddress() doesn't exists * __call() magic method is called. */ $student->getAddress(); |
__callStatic() Magic Method (Available as of version PHP 5.3)
The __callStatic() method is similar to __call method except it is called when code attempts to call a static method which doesn’t exist or inaccessible.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Class Student { private $age; private $name; public function __construct($age, $name) { $this->age = $age; $this->name = $name; } public function getAge() { echo $this->age; } public static function __callStatic($name, $arguments) { echo $name." Doesn't exists"; } } $student = new Student(18, "John"); /* * getAddress() static method doesn't exists * __callStatic() magic method is called. */ $student::getAddress(); |
__toString() Magic Method
The __toString() method is called when a code tries to treat an object like a string. This method doesn’t accept any argument.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Class Student { private $age; private $name; public function __construct($age, $name) { $this->age = $age; $this->name = $name; } public function __toString() { return "Student name is ".$this->name." and age is ". $this->age; } } $student = new Student(18, "John"); //__toString() method is called when trying to print object echo $student; |
Abstract class vs interface in PHP
__clone() Magic Method
In PHP, Objects are passed by reference. It means if we copy an object, then it will be copied by reference, not by value.
Difference between call by value & call by reference in PHP
To understand this let’s take an example –
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
Class Student { public $age; public $name; public function __construct($age, $name) { $this->age = $age; $this->name = $name; } public function getAge() { return $this->age; } } $student = new Student(18, "John"); $student1 = $student; //print student object var_dump($student); //print student1 object var_dump($student1); /* *Change the value of age property in a student object *student1 object is also changed */ $student->age = 20; //print student object var_dump($student); //print student1 object var_dump($student1); /****** Output ********/ object(Student)#1 (2) { ["age"]=> int(18) ["name"]=> string(4) "John" } object(Student)#1 (2) { ["age"]=> int(18) ["name"]=> string(4) "John" } object(Student)#1 (2) { ["age"]=> int(20) ["name"]=> string(4) "John" } object(Student)#1 (2) { ["age"]=> int(20) ["name"]=> string(4) "John" } |
In order to create a copy of an object, we need to use clone keyword.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
Class Student { public $age; public $name; public function __construct($age, $name) { $this->age = $age; $this->name = $name; } public function getAge() { return $this->age; } } $student = new Student(18, "John"); //create a copy of student object $student1 = clone $student; //Change the value of age property in student object $student->age = 20; //print student object var_dump($student); //print student1 object var_dump($student1); |
The __clone() magic method is used to change the behaviour of a clone object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
Class Student { public $age; public $name; public function __construct($age, $name) { $this->age = $age; $this->name = $name; } public function getAge() { return $this->age; } public function __clone() { $this->name = "Another student"; } } $student = new Student(18, "John"); $student1 = clone $student; //Change the value of age property in student object $student->age = 20; //print student object var_dump($student); //print student1 object var_dump($student1); /*** Output ***/ object(Student)#1 (2) { ["age"]=> int(20) ["name"]=> string(4) "John" } object(Student)#2 (2) { ["age"]=> int(18) ["name"]=> string(15) "Another student" } |
Cons of Magic Method
1. Magic methods are slow.
2. Magic methods are public so it ignores scope.