您现在的位置是:首页 >技术教程 >PHP中的魔术方法网站首页技术教程

PHP中的魔术方法

斯密码赛我是美女 2025-05-05 00:01:03
简介PHP中的魔术方法

在 PHP 中,以两个下划线 __ 开头的方法被称为魔术方法,它们在特定场景下会自动被调用,以下是一些常见的魔术方法:

1.__construct():类的构造函数,在对象创建完成后第一个自动调用,用于执行初始化任务,如对成员属性赋予初始值。每个类若未显式声明,会默认存在一个无参且内容为空的构造方法。同一类中只能声明一个构造方法,PHP 不支持构造函数重载。例如:

class Person {
    public $name;
    public $age;
    public function __construct($name = "", $age = 22) {
        $this->name = $name;
        $this->age = $age;
    }
    public function say() {
        echo "我叫:". $this->name. ",年龄:". $this->age;
    }
}
$person1 = new Person();
echo $person1->say(); // 输出:我叫:,年龄:22
$person2 = new Person("小明", 18);
echo $person2->say(); // 输出:我叫:小明,年龄:18

2.__destruct():类的析构函数,当对象不再被使用、即将被销毁时调用,可用于执行清理工作,如关闭文件句柄、释放资源等。

class FileHandler {
    private $file;
    public function __construct($filename) {
        $this->file = fopen($filename, 'r');
    }
    public function __destruct() {
        if ($this->file) {
            fclose($this->file);
        }
    }
}

3.__call():当调用对象中不存在的方法时触发,可用于捕获方法调用,实现如代理模式(在代理类中定义一个捕获方法,代理类中没有这个方法时去调用真实对象里的方法)等设计模式。它接收两个参数,$name 为方法名,$arguments 为方法参数数组。

class Proxy {
    public function __call($name, $arguments) {
        echo "调用了不存在的方法 $name ,参数为:". implode(', ', $arguments);
    }
}
$proxy = new Proxy();
$proxy->nonexistentMethod('param1', 'param2');

4.__callStatic():在静态上下文中调用不存在的静态方法时执行,与 __call() 类似,用于处理静态方法的动态调用。

class StaticProxy {
    public static function __callStatic($name, $arguments) {
        echo "调用了不存在的静态方法 $name ,参数为:". implode(', ', $arguments);
    }
}
StaticProxy::nonexistentStaticMethod('param1', 'param2');

5.__get():当读取一个不存在的属性时调用,可用于实现属性的重载。

class PropertyOverload {
    private $data = [];
    public function __get($name) {
        return $this->data[$name]?? null;
    }
}
$obj = new PropertyOverload();
echo $obj->nonExistentProperty;

6.__set():在给一个不存在的属性赋值时触发。

class PropertyOverload {
    private $data = [];
    public function __set($name, $value) {
        $this->data[$name] = $value;
    }
}
$obj = new PropertyOverload();
$obj->newProperty = "value";

7.__isset():使用 isset() 或 empty() 检测一个不存在的属性时调用。

class PropertyCheck {
    private $data = [];
    public function __isset($name) {
        return isset($this->data[$name]);
    }
}
$obj = new PropertyCheck();
var_dump(isset($obj->nonExistentProperty));

8.__unset():使用 unset() 销毁一个不存在的属性时触发。

class PropertyDestroy {
    private $data = [];
    public function __unset($name) {
        if (isset($this->data[$name])) {
            unset($this->data[$name]);
        }
    }
}
$obj = new PropertyDestroy();
$obj->property = "value";
unset($obj->property);

9.__toString():当对象被当作字符串使用(如在 echo 语句中)时调用,用于定义对象的字符串表示形式。

class ObjectToString {
    public function __toString() {
        return "这是一个对象";
    }
}
$obj = new ObjectToString();
echo $obj;

10.__invoke():尝试以调用函数的方式调用对象时触发,使对象可像闭包一样被调用。

class InvokableObject {
    public function __invoke($param) {
        echo "对象被调用,参数为:". $param;
    }
}
$obj = new InvokableObject();
$obj('test');

补充(闭包:closure = function() use (var) { echo var; };这行代码,closure是一个变量,它被赋值为一个匿名函数,就是function() { echo var; }这部分。use (var)的意思是,让这个匿名函数可以访问外部的$var变量。然后在函数内部,用echo var;来输出这个变量的值。这样就定义好了一个闭包。当你调用closure();的时候,它就会执行匿名函数里的代码,也就是输出$var的值。n'b)

11.__sleep():在序列化对象时调用,可清理对象并返回一个包含所有要序列化属性名称的数组。(可以进行清理工作,同时会返回数组里面是你要序列化的属性,我的理解是轻减了序列化的内容)

class SerializableObject {
    private $data1;
    private $data2;
    public function __sleep() {
        return ['data1', 'data2'];
    }
}
$obj = new SerializableObject();
$serialized = serialize($obj);

12.__wakeup():PHP 反序列化对象时调用,通常用于重新建立数据库连接或执行其他初始化任务。(和__sleep相反,可以重新连接数据库,恢复数据等操作)

class SerializableObject {
    private $data1;
    private $data2;
    public function __wakeup() {
        // 重新建立数据库连接等初始化操作
    }
}
$serialized = '...'; // 假设已存在序列化后的字符串
$obj = unserialize($serialized);
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。