• 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经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。

    <?php
    class 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属性的新值. 这个例子被设计成自我保持. 在实际开发中,你可能发现包含资源(如图像或数据流)的对象需要这些方法。

     <?php
    class 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

  • 相关阅读:
    必须克服的10种不良阅读习惯
    如何提升你的影响力
    爱情在线:拥抱变化的男女爱情!
    时间与生命
    女子最钟爱的五种男人
    社交常用表达:把人家的名字给忘了怎么办?
    最常用英语口头禅[推荐]
    中秋节的来历
    学会欣赏自己
    转帖]白领:4大行业通往高薪之路
  • 原文地址:https://www.cnblogs.com/uduemc/p/4122156.html
Copyright © 2020-2023  润新知