PHP 魔术方法 - __set_state()
如果我说一个方法,大家一定知道,那就是 var_dump()
,因为它不仅会输出变量的值,还会输出变量的类型。如果我说另一个方法,可能就很少人知道了,那个方法是 var_export()
,它的功能和 var_dump()
相同,不同的是,它仅会输出变量的值。
我们来看一段代码
<?php $person = array('name'=>'Yufei','age'=>30,'sex'=>'Male'); var_export($person); echo "\n";
运行结果如下
[yufei@localhost php]$ php demo.php array ( 'name' => 'Yufei', 'age' => 30, 'sex' => 'Male', )
知道这个方法的人,一般也就用它来输出 数组 ( array ) 。很少人会用它来输出基础类型,因为那是 echo
的地盘,但如果用它来输出一个对象会怎么样呢 ?
我们接着看下面这段代码
<?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('Yufei',30,'Male'); var_export($person); echo "\n";
运行结果如下
[yufei@localhost php]$ php demo.php Person::__set_state(array( 'sex' => 'Male', 'name' => 'Yufei', 'age' => 30, ))
不知道大家有没有注意到输出结果中的 __set_state()
。这是一个静态方法
如果我们想定制 var_export()
的结果要怎么做呢 ?
静态魔术方法 __set_state()
在 PHP < 5.1.0 的世界里,是没有办法的,但在 5.1.0 以上的版本中,PHP 提供了魔术方法 __set_state()
,当把一个对象传递给 var_export()
的时候,会自动调用该静态魔术方法
该方法的原型如下
static object __set_state ( array $properties )
- 首先,该方法是一个静态方法
- 其次,该方法有一个类型为数组的参数,包含按
array('property' => value, ...)
格式排列的类属性 - 再次,该方法必须有一个返回值,返回一个对象,一般情况下也是该类的一个实例
不过这个方法的使用方式有点特别,你看了范例就懂了
范例
往常的,按照之前的魔术方法的使用方式,我们肯定会写出如下的代码
<?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 ) { echo "调用 __set_state() 方法\n"; $a = new Person(); $a->name = $an_array['name']; $a->school = 'HuaQiao'; return $a; } } $person = new Person('Yufei',30); $b = var_export($person, true); var_dump($b);
但是,当你运行的时候,会大吃一惊,因为输出结果如下
[yufei@localhost php]$ php demo.php string(87) "Person::__set_state(array( 'sex' => 'Male', 'name' => 'Yufei', 'age' => 30, ))"
难道是我们的函数写错了 ? 难道是它不是一个静态方法 ? 难道....为什么什么都没有
因为没有输出 调用 __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 ) { echo "调用 __set_state() 方法\n"; $a = new Person(); $a->name = $an_array['name']; $a->school = 'HuaQiao'; return $a; } } $person = new Person('Yufei',30); $b = var_export($person, true); var_dump($b); eval ( '$c = ' . $b . ';' ); var_dump($c);
运行结果如下
[yufei@localhost php]$ php demo.php string(87) "Person::__set_state(array( 'sex' => 'Male', 'name' => 'Yufei', 'age' => 30, ))" 调用 __set_state() 方法 object(Person)#2 (4) { ["sex"]=> string(4) "Male" ["name"]=> string(5) "Yufei" ["age"]=> int(25) ["school"]=> string(7) "HuaQiao" }
这又是什么操作 ? 竟然又被调用了 ?
所以,从某些方面说,这个静态魔术方法的官方介绍,也是够坑的了 ?
这个魔术方法在什么时候调用呢 ?
在把 var_export()
方法生成的结果还原会对象的时候执行,可是,那为什么第一次输出的结果里没有 school
属性呢? 令人费解