PHP 魔术方法 __sleep __wakeup(四)

王朝学院·作者佚名  2016-05-25
窄屏简体版  字體: 小  |  中  |  大  |  超大  

php 魔术方法 __sleep __wakeup(四)串行化serialize可以把变量包括对象,转化成连续bytes数据. 你可以将串行化后的变量存在一个文件里或在网络上传输. 然后再反串行化还原为原来的数据. 你在反串行化类的对象之前定义的类,PHP可以成功地存储其对象的属性和方法. 有时你可能需要一个对象在反串行化后立即执行. 为了这样的目的,PHP会自动寻找__sleep和__wakeup方法.

当一个对象被串行化,PHP会调用__sleep方法(如果存在的话). 在反串行化一个对象后,PHP 会调用__wakeup方法. 这两个方法都不接受参数. __sleep方法必须返回一个数组,包含需要串行化的属性. PHP会抛弃其它属性的值. 如果没有__sleep方法,PHP将保存所有属性.

在程序执行前,serialize() 函数会首先检查是否存在一个魔术方法 __sleep.如果存在,__sleep()方法会先被调用,然后才执行串行化(序列化)操作。这个功能可以用于清理对象,并返回一个包含对象中所有变量名称的数组。如果该方法不返回任何内容,则NULL被序列化,导致一个E_NOTICE错误。与之相反,unserialize()会检查是否存在一个__wakeup方法。如果存在,则会先调用__wakeup方法,预先准备对象数据。

__sleep方法常用于提交未提交的数据,或类似的操作。同时,如果你有一些很大的对象,不需要保存,这个功能就很好用。__wakeup经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。

<?phpclass Connection { PRotected $link; private $server, $username, $passWord, $db; public function __construct($server, $username, $password, $db) { $this->server = $server; $this->username = $username; $this->password = $password; $this->db = $db; $this->connect(); } private function connect() { $this->link = MySQL_connect($this->server, $this->username, $this->password); mysql_select_db($this->db, $this->link); } public function __sleep() { return array('server', 'username', 'password', 'db'); } public function __wakeup() { $this->connect(); }}?>

下面例子显示了如何用__sleep和 __wakeup方法来串行化一个对象. Id属性是一个不打算保留在对象中的临时属性. __sleep方法保证在串行化的对象中不包含id属性. 当反串行化一个User对象,__wakeup方法建立id属性的新值. 这个例子被设计成自我保持. 在实际开发中,你可能发现包含资源(如图像或数据流)的对象需要这些方法。

<?phpclass user { public $name; public $id; function __construct() { // 给id成员赋一个uniq id $this->id = uniqid(); } function __sleep() { //此处不串行化id成员 return(array('name')); } function __wakeup() { $this->id = uniqid(); } }$u = new user();$u->name = "Leo"; $s = serialize($u); //serialize串行化对象u,此处不串行化id属性,id值被抛弃$u2 = unserialize($s); //unserialize反串行化,id值被重新赋值 //对象u和u2有不同的id赋值print_r($u);print_r($u2);?>

例三:__wakeup方法的一个缺陷需要注意,如果你打算unserialize一个对象,你

<?php class A { public $b; public $name; } class B extends A { public $parent; public function __wakeup() { var_dump($parent->name); } } $a = new A(); $a->name = "foo"; $a->b = new B(); //我们期望这里输出:foo,但实际在后面的代码执行之后,实际输出NULL.$a->b->parent = $a; $s = serialize($a); $a = unserialize($s); ?>

原因: $b 对象在$name之前unserialized了. 所以在B::__wakeup执行时, $a->name还没有被赋值

所以,一定要小心你定义类中变量的执行顺序。

原文地址:http://blog.sina.com.cn/s/blog_758ddcb90100yk05.html

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航