Overview
In object-oriented programming, PHP provides a series of magic methods, which provide a lot of convenience for programming. Magic methods in PHP usually start with __ (two underscores) and do not require explicit calls but are triggered by certain conditions. This article briefly summarizes the magic methods available in PHP.
Before you begin
Before summarizing PHP’s magic methods, let’s define two classes for use in later examples:
Copy code The code is as follows:
class Device {
Public $name;
Public $battery;
Public $data = array();
Public $connection;
protected function connect() {
$this->connection = 'resource';
echo $this->name . ' connected' . PHP_EOL;
}
protected function disconnect() {
$this->connection = null;
echo $this->name . ' disconnected' . PHP_EOL;
}
}
class Battery {
private $charge = 0;
Public function setCharge($charge) {
$charge = (int)$charge;
if($charge < 0) {
$charge = 0;
}
elseif($charge > 100) {
$charge = 100;
}
$this->charge = $charge;
}
}
?>
The Device class has four member properties and two member methods. The Battery class has one member property and one member method.
Constructor and destructor
The constructor and destructor are called when the object is created and destroyed respectively. When an object is "destroyed", it means that there is no reference to the object. For example, if the variable that refers to the object is deleted (unset), reassigned, or the script execution ends, the destructor will be called.
__construct()
__construct() The constructor is by far the most commonly used function. When creating an object, you can do some initialization work in the constructor. You can define any number of parameters for the constructor, as long as the corresponding number of parameters is passed in when instantiating. Any exception that occurs in the constructor prevents the object from being created.
Copy code The code is as follows:
class Device {
Public function __construct(Battery $battery, $name) {
$this->battery = $battery;
$this->name = $name;
$this->connect();
}
}
In the above sample code, the constructor of the Device class assigns values to member properties and calls the connect() method.
Copy code The code is as follows:
Declaring the constructor as a private method prevents the object from being created outside the class, which is often used in the simplex pattern.
__desctruct()
The destructor is usually called when the object is destroyed, and the destructor does not receive any parameters. Some cleanup work is often performed in the destructor, such as closing the database connection, etc.
Property Overloading
One thing to note is that "overloading" in PHP is not the same as overloading in most other languages, although they all implement the same function.
The two magic methods involved in property overloading are mainly used to handle property access, defining what happens when we try to access a non-existent (or inaccessible) property.
__get()
The magic method __get() will be called when we try to access a property that does not exist. It receives a parameter that represents the name of the accessed attribute and returns the value of the attribute. In the Device class above, there is a data attribute, which plays a role here, as shown in the following code:
Copy code The code is as follows:
class Device {
Public function __get($name) {
If(array_key_exists($name, $this->data)) {
return $this->data[$name];
}
return null;
}
}
The most common use of this magic method is to extend access control by creating a "read-only" attribute. In the above Battery class, there is a private attribute $charge. We can extend this attribute through the __get() magic method to be readable but not modifyable outside the class. The code is as follows:
Copy code The code is as follows:
class Battery {
private $charge = 0;
Public function __get($name) {
If(isset($this->$name)) {
return $this->$name;
}
return null;
}
}
__set()
The__set() magic method will be called when we try to modify an inaccessible property. It receives two parameters, one representing the name of the property and one representing the value of the property. The sample code is as follows:
Copy code The code is as follows:
class Device {
Public function __set($name, $value) {
// use the property name as the array key
$this->data[$name] = $value;
}
}
__isset()
The __isset() magic method is called when the isset() method is called on an inaccessible property. It receives a parameter representing the name of the property. It should return a Boolean value indicating whether the property exists. The code is as follows:
Copy code The code is as follows:
class Device {
Public function __isset($name) {
return array_key_exists($name, $this->data);
}
}
__unset()
The __unset() magic method will be called when the unset() function is called to destroy an inaccessible attribute. It receives a parameter expressing the name of the attribute.
Convert object to string
Sometimes we need to express objects in the form of strings. If we print an object directly, the program will output an error message: PHP Catchable fatal error: Object of class Device could not be converted to string
__toString()
__toString() will be called when we use the object as a string. It does not receive any parameters. This method allows us to define the representation of the object. The code is as follows:
Copy code The code is as follows:
class Device {
Public function __toString() {
$connected = (isset($this->connection)) ? 'connected' : 'disconnected';
$count = count($this->data);
Return $this->name . ' is ' . $connected . ' with ' . $count . ' items in memory' . PHP_EOL;
}
...
}
__set_state()(PHP 5.1)
Static magic method __set_state(), this method will be called when we use the var_export() function to output the object. The var_export() function is used to convert PHP variables into PHP code. It receives an associative array containing object attribute values as a parameter. The sample code is as follows:
Copy code The code is as follows:
class Battery {
//...
Public static function __set_state(array $array) {
$obj = new self();
$obj->setCharge($array['charge']);
return $obj;
}
//...
}
Clone object
By default, objects are passed by reference. Therefore, when you assign an object to another variable, you only create a reference to the object and do not copy the object. In order to actually copy an object, we need to use the clone keyword.
This "pass by reference" strategy also applies to objects contained within objects. Even if we clone an object, any objects inside the object will not be cloned, so the end result is that both objects share the same internal object. The sample code is as follows:
Copy code The code is as follows:
$device = new Device(new Battery(), 'iMagic');
$device2 = clone $device;
$device->battery->setCharge(65);
echo $device2->battery->charge;
// 65
__clone()
__clone() magic method __clone() can solve the above problem. This magic method is called when the clone keyword is used on an object. In this magic method, we can clone any sub-object. The code is as follows:
Copy code The code is as follows:
class Device {
...
Public function __clone() {
// copy our Battery object
$this->battery = clone $this->battery;
}
...
}
Object serialization
Serialization is the process of converting arbitrary data into string format. Serialization is typically used to store the entire object in a database or write it to a file. When deserializing the stored data, we can get the object before serialization. However, not all data can be serialized, such as database connections. Luckily, there's a magic trick to help us solve this problem.
__sleep()
The magic method __sleep() will be called when serializing an object (calling serialize()). It takes no parameters and should return an array containing all properties that should be serialized. Within this magic method, you can also perform some other operations.
One thing to note is that do not perform any destruction operations in this function, as this may affect the running object.
The sample code is as follows:
Copy code The code is as follows:
class Device {
Public $name;
Public $battery;
Public $data = array();
Public $connection;
//...
Public function __sleep() {
return array('name', 'battery', 'data');
}
//...
}
__wakeup()
The magic method __wakeup() will be called when deserializing the stored object. It does not receive any parameters and does not return any value. You can use it to handle database connections or resources that are lost during serialization. The code is as follows:
Copy code The code is as follows:
class Device {
//...
Public function __wakeup() {
// reconnect to the network
$this->connect();
}
//...
}
Method overloading
PHP also has two magic methods __call() and __callStatic() related to member methods. These two magic methods are similar to attribute overloading methods.
__call()
The magic method __call() will be called when calling a method that does not exist or is inaccessible. It receives two parameters, one is the name of the method to be called, and the other is an array containing the function parameters. We can use this method to call the function of the same name in the child object.
In this example, pay attention to the function call_user_func_array(), which allows us to dynamically call a named function.
The sample code is as follows:
Copy code The code is as follows:
class Device {
//...
Public function __call($name, $arguments) {
// make sure our child object has this method
If(method_exists($this->connection, $name)) {
// forward the call to our child object
return call_user_func_array(array($this->connection, $name), $arguments);
}
return null;
}
//...
}
__callStatic()
The magic method __callStatic() has the same function as __call(). The only difference is that this method will be called when trying to access a non-existent or inaccessible static method. The sample code is as follows:
Copy code The code is as follows:
class Device {
//...
Public static function __callStatic($name, $arguments) {
// make sure our class has this method
If(method_exists('Connection', $name)) {
// forward the static call to our class
return call_user_func_array(array('Connection', $name), $arguments);
}
return null;
}
//...
}
Object as function
Sometimes we need to use objects as functions. Using objects as functions is just like using other ordinary functions, and you can pass parameters.
__invoke()(PHP 5.3)
The magic method __invoke() is called when trying to use the object as a function. Any parameters defined in this method will be used as parameters of the function. The sample code is as follows:
Copy code The code is as follows:
class Device {
//...
Public function __invoke($data) {
echo $data;
}
//...
}
$device = new Device(new Battery(), 'iMagic');
$device('test');
// equiv to $device->__invoke('test')
// Outputs: test
Others:__autoload()
The __autoload() method is not a magic method, but it is very useful. However, with the update of the PHP version, this function is no longer recommended and is replaced by the spl_auto_register() function.