Home >Backend Development >PHP Problem >What is php magic method
The built-in methods named starting with double underscore "__" in PHP are called magic methods, including "__construct()", "__set()", "__get()", "__isset()", "__unset()", "__sleep()", "__wakeup()", "__call()", "__invoke()", etc.; among which "__construct()" is the construction method of the class and is the first step after the object is created. A method that is automatically called by the object.
The operating environment of this tutorial: windows7 system, PHP8 version, DELL G3 computer
Magic method in php
In PHP, methods named starting with a double underscore (__) are called magic methods in PHP, and they play a very important role in PHP. Magic methods include:
Method name | Description |
---|---|
__construct() | Constructor of class |
__destruct() | Destructor of class |
__call($ funName, $arguments) | The __call() method will be called when an undefined or unreachable method is called. |
__callStatic($funName, $arguments) | The __callStatic() method will be called when an undefined or unreachable static method is called. |
#__get($propertyName) | When obtaining a member variable of a class, the __get() method will be called. |
__set($property, $value) | When assigning a member variable of a class, the __set() method will be called. |
__isset($content) | When isset() or empty() is called to assign a value to an undefined or unreachable member, the __isset() method will be transfer. |
__unset($content) | When calling reset() to update an undefined or unreachable member, the __unset() method will be called. |
__sleep() | When executing serialize(), the __sleep() method will be called first. |
__wakeup() | When performing deserialization deserialization(), the __wakeup() method will be called first. |
__toString() | When using the echo method to directly output the display object, the __toString() method is called first. |
__invoke() | When using a function to access an object, the __invoke() method will be called first. |
__set_state($an_array) | When the var_export() method is called, the __set_state() method will be called. |
__clone() | The __clone() method will be called when the object is copied and assigned. |
__autoload($className) | Called when trying to load an undefined class. |
__debugInfo() | Output debug information. |
This article will use some examples to demonstrate the use of PHP magic methods.
When an object is created, the constructor method of the PHP class is the first method to be called. Every class has constructor methods. If you don't explicitly define it in the class, there will be a default no-argument class constructor, although it will not be defined in the class.
1) Application of constructor method
The constructor method of a class is usually used to perform some initialization tasks, such as initializing and assigning values to members when creating an object.
2) Declaration format of constructor method in class
function __constrct([parameter list]){ 方法具体实现 //通常为成员变量初始赋值。 }
Note: Only one constructor can be declared in most classes. Because, PHP does not support constructor overloading.
The following is a complete example:
<?php class Person { public $name; public $age; public $sex; /** * 明确定义含参的构造方法 */ public function __construct($name="", $sex="Male", $age=22) { $this->name = $name; $this->sex = $sex; $this->age = $age; } /** * say 方法定义 */ public function say() { echo "Name:" . $this->name . ",Sex:" . $this->sex . ",Age:" . $this->age; } }
Create a $Person1 object without parameters.
$Person1 = new Person(); echo $Person1->say(); //显示:Name:,Sex:Male,Age:22
Call with a parameter "Jams" to create a $Person2 object.
$Person2 = new Person("Jams"); echo $Person2->say(); // 显示: Name: Jams, Sex: Male, Age: 22
Call with 3 parameters to create a $Person3 object.
$Person3 = new Person ("Jack", "Male", 25); echo $Person3->say(); // 显示:Name: Jack, Sex: Male, Age: 25
The destructor is the opposite of the constructor.
The destructor allows you to perform some operations before destroying the object, such as closing the file, clearing the result set, etc.
Destructor is a new feature introduced in PHP 5.
The declaration of the destructor is similar to the constructor, starting with two underscores, and the name is fixed to __destruct()
.
function __destruct() { //method body }
The destructor cannot take parameters.
Destructor is generally not common in classes. It is an optional part of the class and is usually used to complete some cleanup tasks before the class is destroyed.
This is an example of using the destructor:
<?php class Person{ public $name; public $age; public $sex; public function __construct($name="", $sex="Male", $age=22) { $this->name = $name; $this->sex = $sex; $this->age = $age; } /** * say method */ public function say() { echo "Name:".$this->name.",Sex:".$this->sex.",Age:".$this->age; } /** * declare a destructor method */ public function __destruct() { echo "Well, my name is ".$this->name; } } $Person = new Person("John"); unset($Person); //destroy the object of $Person created above
Output result
Well, my name is John
This method accepts two parameters. The first parameter is the undefined method name, and the second parameter is an array composed of the parameters passed in to the method
function __call(string $function_name, array $arguments) { // method body }
When calling an undefined method in the program, __call()
The method will be called.
Example
<?php class Person { function say() { echo "Hello, world!<br>"; } function __call($funName, $arguments) { echo "The function you called:" . $funName . "(parameter:" ; // Print the method's name that is not existed. print_r($arguments); // Print the parameter list of the method that is not existed. echo ")does not exist!!<br>\n"; } } $Person = new Person(); $Person->run("teacher"); // If the method which is not existed is called within the object, then the __call() method will be called automatically. $Person->eat("John", "apple"); $Person->say();
Display results
The function you called: run (parameter: Array([0] => teacher)) does not exist! The function you called: eat (parameter: Array([0] => John[1] => apple)) does not exist! Hello world!
When an undefined static method is called in the program, __callStatic( )
method will be called automatically. The usage of
__callStatic()
is similar to __call()
. Here is an example:
<?php class Person { function say() { echo "Hello, world!<br>"; } public static function __callStatic($funName, $arguments) { echo "The static method you called:" . $funName . "(parameter:" ; // 打印出未定义的方法名。 print_r($arguments); // 打印出未定义方法的参数列表。 echo ")does not exist!<br>\n"; } } $Person = new Person(); $Person::run("teacher"); // 如果此项目内不存在的方法被调用了,那么 __callStatic() 方法将被自动调用。 $Person::eat("John", "apple"); $Person->say();
The execution result is as follows:
The static method you called: run (parameter: Array([0] => teacher)) does not exist! The static method you called: eat (parameter: Array([0] => John[1] => apple)) does not exist! Hello world!
When you try to access the private properties of the object externally, the application will throw an exception and end the run. We can solve this problem using __get
method. This method can obtain the value of a private property from outside the object. An example is as follows
<?php class Person { private $name; private $age; function __construct($name="", $age=1) { $this->name = $name; $this->age = $age; } 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("John", 60); // Instantiate the object with the Person class and assign initial values to the properties with the constructor. echo "Name:" . $Person->name . "<br>"; // When the private property is accessed, the __get() method will be called automatically,so we can get the property value indirectly. echo "Age:" . $Person->age . "<br>"; // The __get() method is called automatically,and it returns different values according to the object itself.
The result is shown as follows
Name: John Age: 50
set($property,$value) method is used to set the private properties of the class. After an undefined property is assigned, the set() method is triggered, and the parameters passed are the set property name and value.
The following is the demo code:
<?php class Person { private $name; private $age; public function __construct($name="", $age=25) { $this->name = $name; $this->age = $age; } public function __set($property, $value) { if ($property=="age") { if ($value > 150 || $value < 0) { return; } } $this->$property = $value; } public function say(){ echo "My name is ".$this->name.",I'm ".$this->age." years old"; } } $Person=new Person("John", 25); //请注意,类初始化并为“name”和“age”分配初始值。 $Person->name = "Lili"; // "name" 属性值被成功修改。如果没有__set()方法,程序将报错。 $Person->age = 16; // "age"属性修改成功。 $Person->age = 160; //160是无效值,因此修改失败。 $Person->say(); //输出:My name is Lili, I'm 16 years old。
Code running results:
My name is Lili, I'm 16 years old
Before using the __isset() method, let Let me first explain the usage of isset() method. The isset() method is mainly used to determine whether this variable is set.
If the isset() method is used outside the object, there are two situations:
So for private properties, is there any way to know whether it is set? Of course, as long as the __isset() method is defined in the class, the isset() method can be used outside the class to determine whether the private property is set.
The __isset() method is called when isset() or empty() is called on an undefined or inaccessible property. The following is an example:
<?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 "The {$content} property is private,the __isset() method is called automatically.<br>"; echo isset($this->$content); } } $person = new Person("John", 25); // Initially assigned. echo isset($person->sex),"<br>"; echo isset($person->name),"<br>"; echo isset($person->age),"<br>";
The code running result is as follows:
1 The name property is private,the __isset() method is called automatically. 1 The age property is private,the __isset() method is called automatically. 1
is similar to the isset() method. When it is undefined or When the unset() method is called on an inaccessible property, the unset() method is called. The following is an example:
<?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 "It is called automatically when we use the unset() method outside the class.<br>"; echo isset($this->$content); } } $person = new Person("John", 25); // Initially assigned. unset($person->sex),"<br>"; unset($person->name),"<br>"; unset($person->age),"<br>";
The running result of the code is as follows:
It is called automatically when we use the unset() method outside the class. 1 It is called automatically when we use the unset() method outside the class. 1
serialize() method will check whether there is a magic method __sleep in the class (). If present, this method will be called first, and then the serialization operation will be performed.
__sleep() method is usually used to specify attributes that need to be serialized before saving data. You may find this feature useful if you have some very large objects that don't all need to be saved.
For details, please refer to the following 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 "It is called when the serialize() method is called outside the class.<br>"; $this->name = base64_encode($this->name); return array('name', 'age'); // It must return a value of which the elements are the name of the properties returned. } } $person = new Person('John'); // Initially assigned. echo serialize($person); echo '<br/>';
The code running results are as follows:
It is called when the serialize() method is called outside the class. O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25;}
and sleep () method, the wakeup() method is usually used for deserialization operations, such as reestablishing a database connection or performing other initialization operations.
The following are relevant examples:
<?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 "It is called when the serialize() method is called outside the class.<br>"; $this->name = base64_encode($this->name); return array('name', 'age'); // It must return a value of which the elements are the name of the properties returned. } /** * __wakeup */ public function __wakeup() { echo "It is called when the unserialize() method is called outside the class.<br>"; $this->name = 2; $this->sex = 'Male'; // There is no need to return an array here. } } $person = new Person('John'); // Initially assigned. var_dump(serialize($person)); var_dump(unserialize(serialize($person)));
The code running results are as follows:
It is called when the serialize() method is called outside the class. string(58) "O:6:"Person":2:{s:4:"name";s:8:"5bCP5piO";s:3:"age";i:25;}" It is called when the unserialize() method is called outside the class. object(Person)#2 (3) { ["sex"]=> string(3) "Male" ["name"]=> int(2) ["age"]=> int(25) }
When using the echo method to directly print the object, Call the __toString() method.
Note: This method must return a string, otherwise a fatal error will be raised at level E_RECOVERABLE_ERROR
. And you can't throw exception in __toString() method either.
The following are relevant examples:
<?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('John'); // Initially assigned. echo $person;
The results of running the code are as follows:
go go go
So, what if the __toString() method is not defined in the class? Let's try it out.
<?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('John'); // Initially assigned. echo $person;
The results of running the code are as follows:
Catchable fatal error: Object of class Person could not be converted to string in D:\phpStudy\WWW\test\index.php on line 18
显然,它在页面上报告了一个致命错误,PHP语法不支持这样的写法。
当您尝试以调用函数的方式调用对象时,__ invoke()方法将被自动调用。
注意:此功能仅在PHP 5.3.0及更高版本中有效。
下面是相关实例:
<?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'; } } $person = new Person('John'); // Initially assigned. $person();
运行代码结果如下:
This is an object
如果坚持使用对象作为方法(但未定义__invoke()方法),则将得到以下结果:
Fatal error: Function name must be a string in D:\phpStudy\WWW\test\index.php on line 18
从PHP 5.1.0开始,在调用var_export()导出类代码时会自动调用__set_state()方法。
__set_state()方法的参数是一个包含所有属性值的数组,其格式为array('property'=> value,...)
在以下示例中,我们没有定义__set_state()方法:
<?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('John'); // Initially assigned. var_export($person);
执行代码结果如下:
Person::__set_state(array( 'sex' => 'Male', 'name' => 'John', 'age' => 25, ))
显然,对象的属性已打印。
现在让我们看看定义__set_state()方法的另一种情况:
<?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('John'); // Initially assigned. $person->name = 'Jams'; var_export($person);
执行代码结果如下:
Person::__set_state(array( 'sex' => 'Male', 'name' => 'Jams', 'age' => 25, ))
在PHP中,我们可以使用clone关键字通过以下语法克隆对象:
$copy_of_object = clone $object;
但是,使用clone关键字只是一个浅拷贝,因为所有引用的属性仍将指向原始变量。
如果在对象中定义了clone()方法,则将在复制生成的对象中调用clone()方法,该方法可用于修改属性的值(如有必要)。
下面是相关的示例:
<?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__."your are cloning the object.<br>"; } } $person = new Person('John'); // Initially assigned. $person2 = clone $person; var_dump('persion1:'); var_dump($person); echo '<br>'; var_dump('persion2:'); var_dump($person2);
运行代码结果如下:
Person::__clone your are cloning the object. string(9) "persion1:" object(Person)#1 (3) { ["sex"]=> string(3) "Male" ["name"]=> string(6) "John" ["age"]=> int(25) } string(9) "persion2:" object(Person)#2 (3) { ["sex"]=> string(3) "Male" ["name"]=> string(6) "John" ["age"]=> int(25) }
__autoload()方法可以尝试加载未定义的类。
过去,如果要在程序文件中创建100个对象,则必须使用include()或require()来包含100个类文件,或者必须在同一类文件中定义100个类。 例如以下:
/** * file non_autoload.php */ require_once('project/class/A.php'); require_once('project/class/B.php'); require_once('project/class/C.php'); . . . if (ConditionA) { $a = new A(); $b = new B(); $c = new C(); // … } else if (ConditionB) { $a = newA(); $b = new B(); // … }
那么,如果我们使用__autoload()方法呢?
/** * file autoload_demo.php */ function __autoload($className) { $filePath = “project/class/{$className}.php”; if (is_readable($filePath)) { require($filePath); } } if (ConditionA) { $a = new A(); $b = new B(); $c = new C(); // … } else if (ConditionB) { $a = newA(); $b = new B(); // … }
当PHP引擎第一次使用类A时,如果未找到类A,则autoload方法将被自动调用,并且类名称“ A”将作为参数传递。因此,我们在autoload()方法中需要做的是根据类名找到相应的类文件,然后将其包含在内。如果找不到该文件,则php引擎将抛出异常。
当执行 var_dump()
方法时,__debugInfo()
方法会被自动调用。如果 __debugInfo()
方法未被定义,那么 var_dump
方法或打印出这个对象的所有属性。
举例说明:
<?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));
执行结果:
object(C)#1 (1) { ["propSquared"]=> int(1764) }
注意:__debugInfo() 方法应该在 PHP 5.6.0 及以上版本中使用。
以上就是我所了解的 PHP
魔术方法,其中常用的包括 __set()
还有 __get()
和 __autoload()
。如果你还有其他疑问,可以从 PHP
官方网站获得更多帮助。
推荐学习:《PHP视频教程》
The above is the detailed content of What is php magic method. For more information, please follow other related articles on the PHP Chinese website!