zoukankan      html  css  js  c++  java
  • __sleep和__wakeup

    魔术方法__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还没有被赋值

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

  • 相关阅读:
    [C#]生成缩略图
    [C#]原来DataTable的Distinct竟如此简单!
    [C#] UTF8 ENCODING=QUOTEDPRINTABLE 的解码和编码
    ASP.NET将文件写到另一服务器
    生成machineKey密钥
    Docx转Doc操作(c#)
    Linq学习知识摘记
    HTTP 状态代码
    文件与流相关code
    Web文件的ContentType类型大全
  • 原文地址:https://www.cnblogs.com/leo388/p/4557598.html
Copyright © 2011-2022 走看看