English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In PHP, methods that start with two underscores __ are called magic methods (Magic methods), which play a crucial role in PHP. Magic methods include:
Example
Let's take an example to explain how these magic methods are used.
1. __construct(), the class constructor
In PHP, the constructor is the first method to be automatically called by the object after the object is created. There is a constructor in each class. If it is not explicitly declared, a default constructor without parameters and empty content will exist in the class.
1The role of the constructor
The constructor is usually used to perform some useful initialization tasks, such as assigning initial values to member properties when an object is created.
2The declaration format of a constructor in a class
function __constrct([parameter list]){ Method body //It is usually used to initialize member properties }
3Points to note when declaring a constructor in a class
1Only one constructor can be declared in the same class, because PHP does not support method overloading for constructors.
2, The name of the constructor starts with two underscores __construct()}
Below is an example of it:
<?php class Person { public $name; public $age; public $sex; /** * Declare a constructor with parameters explicitly */ public function __construct($name="", $sex="男", $age=22) { $this->name = $name; $this->sex = $sex; $this->age = $age; } /** * say method */ public function say() { echo "My name is:" . $this->name . ",Gender:" . $this->sex . ",Age:" . $this->age; } }
Create object $Person1and without any parameters
$Person1 = new Person(); echo $Person1->say(); //Output: My name is: , Gender: Male, Age:27
Create object $Person2and with parameter "Xiao Ming"
$Person2 = new Person("小明"); echo $Person2->say(); //Output: My name is: Zhang San, Gender: Male, Age:27
Create object $Person3and with three parameters
$Person3 = new Person("Li Si","Male",25); echo $Person3->say(); //Output: My name is: Li Si, Gender: Male, Age:25
Secondly, __destruct(), the destructor of the class
Through the above explanation, now we have learned what a constructor is. Then, the corresponding one is the destructor.
The destructor allows certain operations or functions to be executed before a class is destroyed, such as closing files, releasing result sets, etc.
The destructor is a feature in PHP5is the new content introduced recently.
The declaration format of the destructor is similar to that of the constructor __construct(), also starting with two underscores __destruct(), and this destructor name is fixed.
1, The declaration format of the destructor
function __destruct() { //Method body }
Note: The destructor function cannot have any parameters.
2, The role of the destructor
Generally speaking, the destructor is not very commonly used in PHP, it is an optional part of the class, usually used to complete some cleaning tasks before the object is destroyed.
For example, as follows:
<?php class Person{ public $name; public $age; public $sex; public function __construct($name="", $sex="男", $age=22) { $this->name = $name; $this->sex = $sex; $this->age = $age; } /** * say speaking method */ public function say() { echo "My name is:" . $this->name.",Gender:" . $this->sex.",Age:" . $this->age; } /** * Declare a destructor method */ public function __destruct() { echo "I think I can still be saved, my name is" . $this->name; } } $Person = new Person("小明"); unset($Person); //Destroy the object $Person created above
The program outputs as follows:
I think I can still be saved, my name is xiaoming
3. __call(), called when calling an inaccessible method in an object.
This method has two parameters, the first parameter $function_name automatically receives the name of the non-existent method, and the second $arguments receives the multiple parameters of the non-existent method in the form of an array.
1The format of __call() method:
function __call(string $function_name, array $arguments) { // Method body }
2The role of __call() method:
To avoid errors when calling a non-existent method and accidentally causing the program to stop, you can use the __call() method to avoid this.
The program will continue to execute as usual even if the called method does not exist, and the method will be automatically called.
Please refer to the following code:
<?php class Person { function say() { echo "Hello, world!\n"; } /** * Declare this method to handle the calling of non-existent methods in the object */ function __call($funName, $arguments) { echo "The function you called: " . $funName . "(parameters: " ; // Output the name of the called method that does not exist print_r($arguments); // Output the parameter list when calling a non-existent method echo ") does not exist!\n"; // End of line } } $Person = new Person(); $Person->run("teacher"); // If a method does not exist in the object, the __call() method of the object is automatically called $Person->eat("xiaoming", "apple"); $Person->say();
Running result:
The function you called: run(parameters: Array ( [0] => teacher ) ) does not exist!
The function you called: eat(parameters: Array ( [0] => xiaoming [1] => Apple ) ) does not exist!
Hello, world!
4. __callStatic(), called when calling an inaccessible method in a static way
This method is the same as the __call() mentioned above, except that __callStatic() is not prepared for static methods.
Please see the following code:
<?php class Person { function say() { echo "Hello, world!\n"; } /** * Declare this method to handle the calling of non-existent methods in the object */ public static function __callStatic($funName, $arguments) { echo "The static method you called: " . $funName . "(parameters: " ; // Output the name of the called method that does not exist print_r($arguments); // Output the parameter list when calling a non-existent method echo ") does not exist!\n"; // End of line } } $Person = new Person(); $Person::run("teacher"); // If a method does not exist in the object, the __call() method of the object is automatically called $Person::eat("xiaoming", "apple"); $Person->say();
The running result is as follows:
The static method you called: run(parameters: Array ( [0] => teacher ) ) does not exist!
The static method you called: eat(parameters: Array ( [0] => Xiao Ming [1] => Apple ) ) does not exist!
Hello, world!
Five, __get(), is called when obtaining a class member variable
In PHP object-oriented programming, when the class member attributes are set to private, if we try to call it outside, it will appear the error 'Cannot access a private property'. To solve this problem, we can use the magic method __get().
The role of the magic method __get():
During the execution of the program, it can be used to obtain the value of private member properties from the outside of the object.
Let's further understand it through the following __get() instance:
<?php class Person { private $name; private $age; function __construct($name="", $age=1) { $this->name = $name; $this->age = $age; } /** * Add the __get() method in the class, it is automatically called once when directly getting the property value, and the property name is passed in as a parameter to be processed * @param $propertyName * * @return int */ public function __get($propertyName) { if ($propertyName == "age") { if ($this->age > 30) { return $this->age - 10; } else { return $this->$propertyName; } } else { return $this->$propertyName; } } } $Person = new Person("Xiao Ming", 60); // Through an instance of the Person class, and assign initial values to properties through the constructor echo "Name: " . $Person->name . "<br>"; // Directly accessing the private property name, the __get() method is automatically called to indirectly obtain it echo "Age: " . $Person->age . "<br>"; // The __get() method is automatically called, and it will return different values according to the object itself
Running result:
Name: Xiao Ming
Age:50
Six, __set(), is called when setting a class member variable
The role of __set():
`__set( $property, $value )` method is used to set private properties, it is triggered when assigning a value to an undefined property, and the passed parameters are the name and value of the property to be set.
Please see the demonstration code below:
<?php class Person { private $name; private $age; public function __construct($name="", $age=25) { $this->name = $name; $this->age = $age; } /** * The magic method requires two parameters, it is automatically called when assigning a private property directly, and it can also shield some illegal assignments * @param $property * @param $value */ public function __set($property, $value) { if ($property=="age") { if ($value > 150 || $value < 0) { return; } } $this->$property = $value; } /** * 在类中声明说话的方法,将所有的私有属性说出来 */ public function say(){ echo "我叫".$this->name.",今年".$this->age."岁了"; } } $Person=new Person("小明", 25); //注意,初始值将被下面所改变 //自动调用了__set()函数,将属性名name传递给第一个参数,将属性值”李四”传递给第二个参数 $Person->name = "小红"; //赋值成功。如果没有__set(),则出错。 //自动调用了__set()函数,将属性名age传递给第一个参数,将属性值26传递给第二个参数 $Person->age = 16; //赋值成功 $Person->age = 160; //160是一个非法值,赋值失败 $Person->say(); //输出:我叫小红,今年16岁了
Running result:
我叫小红,今年16岁了
七、 __isset(),当对不可访问属性调用isset()或empty()时调用
在查看这个方法之前,我们看一下isset()函数的应用,isset()是检测变量是否被设置的函数,传入一个变量作为参数,如果传入的变量存在则返回true,否则返回false。
那么如果在一个对象外部使用isset()这个函数来检测对象中的成员是否被设置可以吗?
有两种情况,如果对象中成员是公有的,我们就可以使用这个函数来检测成员属性,如果是私有的成员属性,这个函数就不起作用了,原因就是因为私有的被封装了,在外部不可见。那么我们就不可以在对象的外部使用isset()函数来检测私有成员属性是否被设置了吗?当然是可以的,但不是一成不变。你只需要在类中添加一个__isset()方法就可以了,当在类外部使用isset()函数来检测对象中的私有成员是否被设置时,就会自动调用类中的__isset()方法来帮我们完成这样的操作。
__isset()的作用:当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。
Please see the following code demonstration:
<?php class Person { public $sex; private $name; private $age; public function __construct($name="", $age=25, $sex='Male') { $this->name = $name; $this->age = $age; $this->sex = $sex; } /** * @param $content * * @return bool */ public function __isset($content) { echo "Automatically called when using the isset() function to determine the private member {$content} outside the class<br>"; echo isset($this->$content); } } $person = new Person("小明", 25); // Initial assignment echo isset($person->sex),"<br>"; echo isset($person->name),"<br>"; echo isset($person->age),"<br>";
The running result is as follows:
1 // Public can isset()
Automatically called when using the isset() function to determine the private member name outside the class // First echo inside __isset()
1 // Second echo inside __isset()
Automatically called when using the isset() function to determine the private member age outside the class // First echo inside __isset()
1 // Second echo inside __isset()
Eight, __unset(), called when unset() is called on an inaccessible property.
Before looking at this method, let's first take a look at the unset() function. The unset() function is used to delete a specified variable and return true, with the parameter being the variable to be deleted.
So can you use the unset() function to delete the member properties inside an object from outside the object?
Of course, there are also two cases here:
1If the member property inside an object is public, you can use this function to delete the public property of the object outside the object.
2If the member property of the object is private, I have no permission to delete it using this function.
Although there are two cases above, what I want to say is that if you add the __unset() method inside an object, you can delete the private member properties of the object outside the object. After adding the __unset() method inside the object, when using the "unset()" function to delete the private member properties inside the object from outside the object, the object will automatically call the __unset() function to help us delete the private member properties inside the object.
Please see the following code:
<?php class Person { public $sex; private $name; private $age; public function __construct($name="", $age=25, $sex='Male') { $this->name = $name; $this->age = $age; $this->sex = $sex; } /** * @param $content * * @return bool */ public function __unset($content) { echo "Automatically called when using the unset() function to delete private members outside the class<br>"; echo isset($this->$content); } } $person = new Person("小明", 25); // Initial assignment unset($person->sex); unset($person->name); unset($person->age);
Running result:
Automatically called when using the unset() function to delete private members outside the class
1Automatically called when using the unset() function to delete private members outside the class
Nine, __sleep(), this function will be called first when executing serialize()
serialize() function will check if there is a magic method __sleep() in the class. If it exists, this method will be called first, and then the serialization operation will be executed.
This feature can be used to clean up objects and return an array containing all variable names in the object that should be serialized.
If this method returns nothing, NULL will be serialized and an E_NOTICE level error will be generated.
Note:
__sleep() cannot return the names of private members of the superclass. This will cause an E_NOTICE level error. Serializable interface can be used instead.
Function:
__sleep() method is often used to commit uncommitted data, or similar cleanup operations. At the same time, if there are some very large objects that do not need to be saved in full, this feature is very useful.
Please refer to the following code for details:
<?php class Person { public $sex; public $name; public $age; public function __construct($name="", $age=25, $sex='Male') { $this->name = $name; $this->age = $age; $this->sex = $sex; } /** * @return array */ public function __sleep() { echo "When using serialize() outside the class, the __sleep() method here will be called<br>"; $this->name = base64_encode($this->name); return array('name', 'age'); // It must return a number, with the elements inside representing the names of the returned properties } } $person = new Person('Xiao Ming'); // Initial assignment echo serialize($person); echo '<br/>';
Code execution result:
The __sleep() method is called here when serialize() is used outside the class
O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25;}
Ten, __wakeup(), this function will be called first when executing unserialize()
If __sleep() is white, then __wakeup() is black.
Then why is that?
Because:
On the contrary, `unserialize()` will check if there is a `__wakeup()` method. If it exists, it will call the `__wakeup` method first to prepare the resources needed by the object in advance.
Function:
__wakeup() is often used in deserialization operations, such as re-establishing database connections, or performing other initialization operations.
Let's take a look at the code:
<?php class Person { public $sex; public $name; public $age; public function __construct($name="", $age=25, $sex='Male') { $this->name = $name; $this->age = $age; $this->sex = $sex; } /** * @return array */ public function __sleep() { echo "When using serialize() outside the class, the __sleep() method here will be called<br>"; $this->name = base64_encode($this->name); return array('name', 'age'); // It must return a number, with the elements inside representing the names of the returned properties } /** * __wakeup */ public function __wakeup() { echo "When using unserialize() outside the class, the __wakeup() method here will be called<br>"; $this->name = 2; $this->sex = 'male'; // No need to return an array here } } $person = new Person('Xiao Ming'); // Initial assignment var_dump(serialize($person)); var_dump(unserialize(serialize($person)));
Running result:
The __sleep() method is called here when serialize() is used outside the class
string(58) "O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25};" When __sleep() method is called here when serialize() is used outside the class
The __wakeup() method is called here when unserialize() is used outside the class
object(Person)#2 (3) { ["sex"]=> string(3) "男" ["name"]=> int(2) ["age"]=> int(25) }
Eleven, __toString(), the response method when a class is treated as a string
Function:
__toString() method is used to specify how a class should respond when it is treated as a string. For example, `echo $obj;` should display what.
Note:
This method must return a string, otherwise, a `E_RECOVERABLE_ERROR` level fatal error will be emitted.
Warning:
You cannot throw an exception in the __toString() method. This will cause a fatal error.
Code:
<?php class Person { public $sex; public $name; public $age; public function __construct($name="", $age=25, $sex='Male') { $this->name = $name; $this->age = $age; $this->sex = $sex; } public function __toString() { return 'go go go'; } } $person = new Person('Xiao Ming'); // Initial assignment echo $person;
Result:
go go go
So what happens if the magic method __toString() does not exist in the class? Let's test it out:
Code:
<?php class Person { public $sex; public $name; public $age; public function __construct($name="", $age=25, $sex='Male') { $this->name = $name; $this->age = $age; $this->sex = $sex; } } $person = new Person('Xiao Ming'); // Initial assignment echo $person;
Result:
Catchable fatal error: Object of class Person could not be converted to string in D:\phpStudy\WWW\test\index.php on line 18
It is obvious that the page reported a fatal error, which is not allowed by the syntax.
Twelve, __invoke(), the response method when calling an object as a function
Function:
When an object is called as a function, the __invoke() method is automatically called.
Note:
This feature is only available in PHP 5.3is valid from version .0 and above.
Let's go straight to the code:
<?php class Person { public $sex; public $name; public $age; public function __construct($name="", $age=25, $sex='Male') { $this->name = $name; $this->age = $age; $this->sex = $sex; } public function __invoke() { echo 'This is an object, you know'; } } $person = new Person('Xiao Ming'); // Initial assignment $person();
Check the running result:
This is an object, you know
Of course, if you insist on using an object as a function method, you will get the following result:
Fatal error: Function name must be a string in D:\phpStudy\WWW\test\index.php on line 18
Thirteen, __set_state(), this static method is called when the var_export() function is used to export the class.
Function:
Since PHP 5.1.0 onwards, when the var_export() function is used to export the class, this static method will be automatically called.
Parameters:
The only parameter of this method is an array that contains class properties arranged in the format array('property' => value, ...).
Let's first take a look at how the code and the running results are without adding __set_state():
The code above:
<?php class Person { public $sex; public $name; public $age; public function __construct($name="", $age=25, $sex='Male') { $this->name = $name; $this->age = $age; $this->sex = $sex; } } $person = new Person('Xiao Ming'); // Initial assignment var_export($person);
See the result:
Person::__set_state(array( 'sex' => '男', 'name' => '小明', 'age' => 25, ))
It is clear that all properties of the object are printed out
After adding __set_state():
Continue with the code:
<?php class Person { public $sex; public $name; public $age; public function __construct($name="", $age=25, $sex='Male') { $this->name = $name; $this->age = $age; $this->sex = $sex; } public static function __set_state($an_array) { $a = new Person(); $a->name = $an_array['name']; return $a; } } $person = new Person('Xiao Ming'); // Initial assignment $person->name = '小红'; var_export($person);
Continue to see the result:
Person::__set_state(array( 'sex' => '男', 'name' => '小红', 'age' => 25, ))
Fourteen, __clone(), is called when object duplication is completed
In most cases, we do not need to fully duplicate an object to obtain its properties. However, there is a situation where it is indeed necessary: if you have a GTK window object that holds resources related to the window. You might want to duplicate a new window, keeping all properties the same as the original window, but it must be a new object (because if it is not a new object, any changes in one window will affect the other window). There is also another situation: if object A contains a reference to object B, when you duplicate object A, you want the object used to no longer be object B but a copy of B, then you must get a copy of object A.
Function:
Object duplication can be achieved by using the clone keyword (if possible, this will call the object's __clone() method). The __clone() method in the object cannot be called directly.
Syntax:
$copy_of_object = clone $object;
Note:
After the object is copied, PHP 5 Perform a shallow copy (shallow copy) on all properties of the object. All reference properties will still be a reference to the original variable.
When the copy is complete, if the __clone() method is defined, the __clone() method in the newly created object (the object generated by the copy) will be called, which can be used to modify the value of the properties (if necessary).
Look at the code:
<?php class Person { public $sex; public $name; public $age; public function __construct($name="", $age=25, $sex='Male') { $this->name = $name; $this->age = $age; $this->sex = $sex; } public function __clone() { echo __METHOD__."You are cloning an object<br>"; } } $person = new Person('Xiao Ming'); // Initial assignment $person2 = clone $person; var_dump('persion1:'); var_dump($person); echo '<br>'; var_dump('persion2:'); var_dump($person2);
See the result:
Person::__clone You are cloning an object
string(9) "persion1:" object(Person)#1 (3) { ["sex"]=> string(3) "Male" ["name"]=> string(6) "Xiao Ming" ["age"]=> int(25) }
string(9) "persion2:" object(Person)#2 (3) { ["sex"]=> string(3) "Male" ["name"]=> string(6) "Xiao Ming" ["age"]=> int(25) }
Clone succeeded.
Fifteenth, __autoload(), attempts to load undefined classes
Function:
You can enable class auto-loading by defining this function.
Before the magic function __autoload() method appeared, if you want to instantiate an object in a program file100 objects, then you must include or require them in100 class files, or you can100 class definitions in the same class file — believe this file will be very large, and then you will suffer.
But with the __autoload() method, you don't have to worry about this anymore, the class will automatically load the specified file before you instantiate the object.
Let's look at it through an example:
Let's take a look at the previous method:
/** * File non_autoload.php */ require_once('project/class/A.php'); require_once('project/class/B.php'); require_once('project/class/C.php'); if (condition A) { $a = new A(); $b = new B(); $c = new C(); // ... business logic } else if (condition B) { $a = new A(); $b = new B(); // ... business logic }
Did you see? Without100, just3It looks a bit烦了. And there will be a problem: if the script executes the 'condition B' branch, the C.php file is actually not necessary to include. Because, any included file, whether used or not, will be compiled by the PHP engine. If not used but compiled, this can be considered as a waste of resources. Furthermore, if C.php includes D.php, D.php includes E.php, and most of the time the 'condition B' branch is executed, then some resources will be wasted compiling the three 'useless' files C.php, D.php, E.php.
So how about using the __autoload() method?
/** * File autoload_demo.php */ function __autoload($className) { $filePath = 'project/class/{$className}.php if (is_readable($filePath)) { require($filePath); } } if (condition A) { $a = new A(); $b = new B(); $c = new C(); // ... business logic } else if (condition B) { $a = new A(); $b = new B(); // ... business logic }
OK, no matter how efficient it is, at least the interface looks much more comfortable, without too much redundant code.
Let's take a look at the efficiency here, let's analyze it:
When the PHP engine first uses class A and cannot find it, it will automatically call the __autoload method and pass the class name 'A' as a parameter. Therefore, what we need to do in __autoload() is to find the corresponding file according to the class name and include it. If our method cannot find it either, the PHP engine will report an error.
Note:
Here you can only use require, because once included, the PHP engine will not call __autoload when it encounters class A again, but will directly use the class A in memory, which will not cause multiple includes.
Expansion:
In fact, PHP has developed to the present day and has implemented the `spl_autoload_register` as __autoload, but this is not within the scope of this article. Those who are interested can read the manual themselves.
Sixteen, __debugInfo(), print the required debugging information
Note:
This method is available in PHP 5.6version 0 and above can be used, if you find that it is ineffective or an error occurs, please check your version.
Look at the code:
<?php class C { private $prop; public function __construct($val) { $this->prop = $val; } /** * @return array */ public function __debugInfo() { return [ 'propSquared' => $this->prop ** 2, ]; } } var_dump(new C(42));
Result:
object(C)#1 (1) { ["propSquared"]=> int(1764) }
Once again, pay attention:
Here the `**` means exponentiation, and it also means exponentiation in PHP5.6version 0 and above can be used, for details, please refer to the PHP manual
Summary
That's all the magic methods I know in PHP. The commonly used ones should be familiar, such as __set(), __get(), __autoload(), and others are also okay, because knowledge is never too much.
Well, if you are interested or if I haven't explained it clearly, you can refer to the official documentation.
PHP Online Manual Address:http://php.net/manual/zh/
That's all for this article. I hope it will be helpful to everyone's learning, and I also hope that everyone will support the Yelling Tutorial more.
Declaration: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, does not edit the content manually, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (When reporting via email, please replace # with @) to report violations, and provide relevant evidence. Once verified, this site will immediately delete the suspected infringing content.