PHP的魔术方法学习

PHP的魔术方法学习

__set_state()

var_export可以把一个集合导出为一串字符串,这些字符串是一些可执行的PHP代码。在php5.1.0的面向对象里,引入了一个叫__set_state的静态方法来使得var_export支持对象实例的导出。当用var_export导出一个实例的时候,所导出字符串里,是调用这个静态方法的代码。这个方法有一个参数,为包含所导出的实例的所有成员属性的一个数组。有点抽象,看下面的例子吧。

<?phpclass o{ public $skill=’php’; public static function __set_state($arr) { foreach ($arr as $k => $v) { $obj->$k = $v; } return $obj; }}$i = new o;$i->age = 21;eval(’$b = ’.var_export($i,true).’;’);//这里的true表示var_export返回所导出的字符串,而不是把它打印出来。print_r($b);/*输出:stdClass Object( [skill] => php [age] => 21)*/?>

__clone()

在php5里,对象间的赋值总是以地址引用来传递的。例如下面这个例子,将会输出66,而不是55.

<?phpclass o{ public $age = 55;}$i = new o;$i2 = $i;$i->age = 66;echo $i2->age;?>

如果要以实际值来传递,则需要用到clone关键词。

<?phpclass o{ public $age = 55;}$i = new o;$i2 = clone $i;$i->age = 66;echo $i2->age;//输出55?>

但是,这里clone的只是$i这个实例。如果$i的某个成员属性也是个实例,那么这个成员属性还是会以引用方法被传递到$i2的。例如下面这个例子:

<?phpclass o{ public $age = 55; public $sub = null;}class o2{ public $p=1;}$i = new o;$i->sub=new o2;$i2 = clone $i;$i->sub->p=5;echo $i2->sub->p;?>

最后输出的是5,而不是1。也就是说,$i和$i2虽然不是指向的虽然不是同一个实例,但是它们的成员属性$sub却是指向同一个实例。这时候,我们必须借助__clone这个方法来对$sub进行复制。在o类里,加入__clone()方法。如下:

<?phpclass o{ public $age = 55; public $sub = null; public function __clone() { $this->sub=clone $this->sub; }}//......?>

这样,在echo $i2->sub->p;的时候,输出的就是传递时候的值1了。

__autoload()

当创建一个实例化的时候,如果对应的类不存在,__autoload()将会被执行,这个函数有一个参数,为所要创建的实例对应的类名。在下面的例子里,当创建一个test类的实例的时候,如果/home/surfchen/project/auto.php存在,则require这个文件,否则打印一个Class test Not Found的错误,并中止当前脚本。