PHP魔术方法总结

__construct()    //用于在创建对象时自动触发当使用 new 关键字实例化一个类时,会自动调用该类的 __construct() 方法
__destruct()     //__destruct() 用于在对象被销毁时自动触发对象的销毁对象的引用计数减少为零来触发
__sleep()        //序列化serialize() 函数会检查类中是否存在一个魔术方法sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组
__wakeup()       //用于在反序列化对象时自动调用unserialize() 会检查是否存在一个 wakeup() 方法,如果存在,则会先调用wakeup()方法
__tostring()     //__tostring() 在对象被当做字符串处理时自动调用比如echo==preg_match()、字符串连接($str="hello".$obj)、
md5()sha1()可以对一个类进行hash,并且会触发这个类的 __toString 方法
__invoke()       //__invoke() 在对象被当做函数处理时自动调用
__call()         //__call($method, $args) 在调用一个不存在的方法时触发, $args是数组的形式
__callStatic()   //__callStatic() 在静态调用或调用成员常量时使用的方法不存在时触发
__set()          //__set() 在给不存在的成员属性或者不可访问(protected  private)的属性赋值时触发,  __set($key, $value)对应$this->name = $value;
__isset()        //__isset() 在对不可访问(protected  private)属性或不存在的属性使用 isset() empty() 时会被触发
__unset()        //__unset() 在对不可访问属性(protected  private)使用 unset() 时会被触发
__clone()        //__clone() 当使用 clone 关键字拷贝完成一个对象后就会触发 
__get()          //__get() 当尝试访问不可访问(protected  private)属性或不存在的属性时会被自动调用
                    即私有属性和不存在的属性

(1)

先执行__wakeup()再执行__destruct()

(2)__call方法的工作原理

当你尝试调用一个对象的方法,而这个方法在该对象类中没有被定义或者不可访问(例如,因为它是私有的或者受保护的),PHP会自动调用这个对象的__call方法。__call方法接收两个参数:$name$arguments$name是一个字符串,包含了被调用的方法名;$arguments是一个数组,包含了传递给方法的参数。

class ExampleClass {

public function __call($name, $arguments) {

echo "尝试调用方法 '$name' ";

echo "带有参数:";

var_dump($arguments);

}}

$obj = new ExampleClass();

$obj->undefinedMethod('参数1', '参数2');

在上面的例子中,undefinedMethod并不存在于ExampleClass中,因此__call方法会被调用,并输出方法名和参数。

// 在Earth::__invoke中
public function __invoke(){
    $oe = $this->onearth;    // 应该是另一个Solar对象
    $ie = $this->inearth;    // 不存在的方法名
    $ote = $this->outofearth; // 关键:这是我们要传递的参数
    $oe->$ie$ote;         // 触发Solar::__call($ie, [$ote])
}
注:无论在哪里触发了__call方法,触发__call的函数和对应的参数,会作为__call方法的参数传入

(3)__construct()

PHP 允许开发者在一个类中定义一个方法作为 构造函数(__construct)。具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作

<?php

class Example{
    private $a;
    private $b;
    private $c;
    public function __construct($a, $b, $c)
    {
        $this->a = $a;
        $this->b = $b;
        $this->c = $c;
    }
    public function getAll(){
        return "A: " . $this->a . "\n" .
            "B: " . $this->b . "\n" .
            "C: " . $this->c . "\n";
    }
}
$a = new Example("我是", "理塘", "丁真"); //这里在创建类时直接传入参数,有时候直接构造$a->b时,若其中有类似$a->b=1;}phpinfo();/*;这样的paylaod时,其中的注释和分号会造成语法错误,此时就可以通过这个传参
echo $a->getAll();

很好理解,他将输出

A: 我是
B: 理塘
C: 丁真

(4)__invoke()

当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。

<?php

class Example {
    public $data;
    public function __construct($data){
        $this->data = data;
    }
    public function __invoke(){
        eval($this->data);
    }
}
$a =  'O:7:"Example":1:{s:4:"data";s:10:"phpinfo();";}';
$b = unserialize($a);
$b();
posted @ 2026-06-18 16:10  Doll_Marker  阅读(10)  评论(0)    收藏  举报