PHP魔术方法详解
__construct()
构造函数用于初始化新创建的对象。PHP 5 之后不推荐使用类名作为构造函数。
class Person {public $name;public $age;public function __construct($name, $age) {$this->name = $name;$this->age = $age;}
}$person = new Person("Alice", 30);
__destruct()
析构函数在对象被销毁前调用,用于释放资源或进行一些清理操作。
class Person {public function __destruct() {// 清理资源或执行其他尾部操作echo "Destroying " . $this->name . "\n";}
}$person = new Person("Alice", 30);
unset($person); // 显示销毁对象
__call($name, $arguments)
尝试调用对象中不可访问的方法时调用。
class Person {private function greet($greeting) {return $greeting . ", I am " . $this->name;}public function __call($name, $arguments) {if (method_exists($this, $name)) {return call_user_func_array([$this, $name], $arguments);}throw new Exception("Call to undefined method " . __CLASS__ . "::$name");}
}$person = new Person("Alice", 30);
echo $person->greet("Hello"); // 不能直接调用private方法,通过__call间接调用
__callStatic($name, $arguments)
尝试调用类中不可访问的静态方法时调用。
class Person {private static function greet($greeting) {return $greeting . ", This is " . __CLASS__;}public static function __callStatic($name, $arguments) {if (method_exists(__CLASS__, $name)) {return forward_static_call_array([__CLASS__, $name], $arguments);}throw new Exception("Call to undefined static method " . __CLASS__ . "::$name");}
}echo Person::greet("Hello"); // 不能直接调用private方法,通过__callStatic间接调用
__get($name)
尝试访问对象中不可访问的属性时调用。
class Person {private $data = array('name' => 'Alice', 'age' => 30);public function __get($name) {if (array_key_exists($name, $this->data)) {return $this->data[$name];}throw new Exception("Undefined property: " . __CLASS__ . "::$name");}
}$person = new Person();
echo $person->name; // 不能直接访问private属性,通过__get间接访问
__set($name, $value)
尝试设置对象中不可访问的属性时调用。
class Person {private $data = array();public function __set($name, $value) {$this->data[$name] = $value;}
}$person = new Person();
$person->name = "Alice"; // 不能直接设置private属性,通过__set间接设置
__isset($name)
当对对象中不可访问的属性调用isset()
或empty()
时调用。
class Person {private $data = array('name' => 'Alice', 'age' => 30);public function __isset($name) {return isset($this->data[$name]);}
}$person = new Person();
var_dump(isset($person->name)); // 输出bool(true)
__unset($name)
尝试对对象中不可访问的属性调用unset()
时调用。
class Person {private $data = array('name' => 'Alice', 'age' => 30);public function __unset($name) {unset($this->data[$name]);}
}$person = new Person();
unset($person->name); // 不能直接unset private属性,通过__unset间接进行
__sleep()
调用serialize()
序列化对象时调用。
class Person {public $name;public $age;private $data;public function __construct($name, $age) {$this->name = $name;$this->age = $age;$this->data = rand(); // 数据不适合序列化}public function __sleep() {// 指定序列化时保存的属性return array('name', 'age');}
}$person = new Person("Alice", 30);
$serializedPerson = serialize($person);
__wakeup()
调用unserialize()
反序列化对象时调用。
class Person {public $name;public $age;public function __wakeup() {// 反序列化之后的操作,例如重新建立数据库连接$this->reconnect();}private function reconnect() {// 重建连接的代码}
}$person = unserialize($serializedPerson);
__serialize()
PHP 7.4及以上版本,当你需要自定义对象的序列化逻辑时使用。
class Person {public $name;public $age;private $data;public function __serialize(): array {// 返回一个数组,包含序列化时需要的所有属性return ['name' => $this->name,'age' => $this->age,];}
}$person = new Person("Alice", 30);
$serializedPerson = serialize($person);
__unserialize(array $data)
PHP 7.4及以上版本,当你需要自定义对象的反序列化逻辑时使用。
class Person {public $name;public $age;public function __unserialize(array $data): void {$this->name = $data['name'];$this->age = $data['age'];// 可以在这里执行其他反序列化后的初始化操作}
}$person = unserialize($serializedPerson);
__toString()
当一个对象被当作字符串使用时自动调用。
class Person {private $name = "Alice";public function __toString() {return $this->name;}
}$person = new Person();
echo $person; // 输出"Alice"
__invoke()
对象作为函数使用时自动调用。
class CallablePerson {public function __invoke($greeting) {return $greeting . ", I am a callable object!";}
}$person = new CallablePerson();
echo $person("Hello"); // 输出"Hello, I am a callable object!"
__set_state($properties)
当使用var_export()
导出类的实例时调用。
class Person {public $name;public $age;public static function __set_state($properties) {$obj = new Person();$obj->name = $properties['name'];$obj->age = $properties['age'];return $obj;}
}$person = new Person();
$person->name = "Alice";
$person->age = 30;
echo var_export($person, true); // 导出类的实例
__clone()
当对象被克隆时自动调用,用于深复制对象中的属性。
class Person {public $name;public $age;public $address;public function __clone() {// 当包含对象时,确保进行深复制$this->address = clone $this->address;}
}$person1 = new Person();
$person1->address = new Address();
$person2 = clone $person1;
__debugInfo()
当使用var_dump()
显示对象信息时调用。
class Person {private $data = array('name' => 'Alice', 'age' => 30);public function __debugInfo() {return ['name' => $this->data['name'],'age' => $this->data['age'],// 隐藏敏感数据或不相关的内部信息];}
}$person = new Person();
var_dump($person);
以上例子提供了一些常见的用法和场景,这些魔术方法让对象的行为更加灵活和可控。