魔术方法
PHP提供了一系列魔术方法, 以双下划线开头, 用于实现特定的功能
PHP 的魔术方法的作用和 Python 的魔术方法非常类似
php
<?php
class MagicClass {
private $data = [];
// 当尝试访问不可访问的属性时调用
public function __get($name) {
echo "__get called for property $name\n";
return array_key_exists($name, $this->data) ? $this->data[$name] : null;
}
// 当尝试设置不可访问的属性时调用
public function __set($name, $value) {
echo "__set called for property $name with value $value\n";
$this->data[$name] = $value;
}
// 当检查不可访问的属性是否存在时调用
public function __isset($name) {
echo "__isset called for property $name\n";
return isset($this->data[$name]);
}
// 当尝试取消设置不可访问的属性时调用
public function __unset($name) {
echo "__unset called for property $name\n";
unset($this->data[$name]);
}
// 当尝试调用不可访问的方法时调用
public function __call($name, $arguments) {
echo "__call called for method $name with arguments: " . implode(', ', $arguments) . "\n";
return "Result of $name";
}
// 当尝试调用不可访问的静态方法时调用
public static function __callStatic($name, $arguments) {
echo "__callStatic called for static method $name with arguments: " . implode(', ', $arguments) . "\n";
return "Static result of $name";
}
// 当对象被当作字符串使用时调用
public function __toString() {
return "This is a MagicClass object\n";
}
// 当对象被克隆时调用
public function __clone() {
echo "__clone called\n";
// 深度克隆需要手动处理
$this->data = array_map(function($value) {
return (is_object($value)) ? clone $value : $value;
}, $this->data);
}
// 当序列化对象时调用
public function __sleep() {
echo "__sleep called\n";
// 返回需要序列化的属性数组
return ['data'];
}
// 当反序列化对象时调用
public function __wakeup() {
echo "__wakeup called\n";
// 重新建立数据库连接等
}
// 当对象被销毁时调用
public function __destruct() {
echo "__destruct called\n";
}
// 当使用var_dump()或print_r()时调用
public function __debugInfo() {
return [
'data' => $this->data,
'count' => count($this->data)
];
}
}
// 使用示例
$obj = new MagicClass();
// 调用__set和__get
$obj->name = "张三"; // __set called for property name with value 张三
echo $obj->name; // __get called for property name \n 张三
// 调用__isset和__unset
var_dump(isset($obj->name)); // __isset called for property name \n bool(true)
unset($obj->name); // __unset called for property name
var_dump(isset($obj->name)); // __isset called for property name \n bool(false)
// 调用__call
echo $obj->nonExistentMethod("arg1", "arg2");
// __call called for method nonExistentMethod with arguments: arg1, arg2
// Result of nonExistentMethod
// 调用__callStatic
echo MagicClass::staticNonExistentMethod("arg1");
// __callStatic called for static method staticNonExistentMethod with arguments: arg1
// Static result of staticNonExistentMethod
// 调用__toString
echo $obj; // This is a MagicClass object
// 调用__clone
$obj2 = clone $obj; // __clone called
// 序列化与反序列化
$serialized = serialize($obj); // __sleep called
$unserialized = unserialize($serialized); // __wakeup called
// var_dump会调用__debugInfo
var_dump($obj);
/*
object(MagicClass)#1 (2) {
["data"]=>
array(0) {
}
["count"]=>
int(0)
}
*/
// 析构函数会在脚本结束时自动调用
// __destruct called