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 属性呢? 令人费解

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.