• SPL--Serializable


    Serializable[自定义序列化的接口]

    实现此接口的类将不再支持 __sleep() 和 __wakeup()

    作用

    为一些高级的序列化场景提供支持。__sleep()和__wakeup()有一些问题,这些问题再SPL中都得到解决。【书上说的,具体的问题之看到了“总结”中的第一个】

    总结:(根据看到的例子总结,绝对地不全)

    1.魔术方法不能序列化基类的私有变量,SPL可以。

    2.SPL可通过子类serialized父类。

    3.SPL可以serialize全部的子类变量,子类不需要重写serialize方法。

    4.在serialize方法中return NULL 来防止序列化。

    以例服人:

    1.魔术方法不能序列化基类私有变量

    <?php
    
    error_reporting( E_ALL );  //开启全部错误提示
    
    class Base {
        private $base;
    
        public function __construct() {
            $this->base = "base";
        }
    }
    
    class Sub extends Base{
        private $sub;
    
        public function __construct() {
            parent::__construct();  //调用父类的构造方法,为父类中的base赋值
            $this->sub = "sub";
        }
    
        public function __sleep() {
            return array( "sub", "base" );
        }
    }
    
    $instance = new Sub();
    $serialized = serialize( $instance );
    echo $serialized."
    ";
    $restored = unserialize( $serialized );
    
    //执行输出
    //Notice: serialize(): "base" returned as member variable from __sleep() but does not exist
    //O:3:"Sub":2:{s:8:"NULSubNULsub";s:3:"sub";s:4:"base";N;}

    使用SPL的Serializable接口就可以解决这个问题

    <?php
    
    error_reporting( E_ALL );  //开启全部错误提示
    
    class Base implements Serializable {
        private $base;
    
        public function __construct() {
            $this->base = "base";
        }
    
        public function serialize() {
            return serialize( $this->base );
        }
    
        public function unserialize( $serialized ) {
            $this->base = unserialize( $serialized );
        }
    
        public function getBase() {
            return $this->base;
        }
    }
    
    class Sub extends Base{
        private $sub;
    
        public function __construct() {
            parent::__construct();  //调用父类的__construct,为父类的base赋值,可通过调用父类的getBase方法获取改值。
            $this->sub = "sub";
        }
    
        public function serialize() {
            $baseSerialized = parent::serialize();  //注意这个地方
            return serialize( array( $this->sub, $baseSerialized ) );
        }
    
        public function unserialize( $serialized ) {
            $temp = unserialize( $serialized );
            $this->sub = $temp[0];
            parent::unserialize( $temp[1] );
        }
    }
    
    $instance = new Sub();
    $serialized = serialize( $instance );
    echo $serialized."
    ";
    $restored = unserialize( $serialized );
    echo $restored->getBase();
    
    //执行输出
    //C:3:"Sub":43:{a:2:{i:0;s:3:"sub";i:1;s:11:"s:4:"base";";}}
    //base

    2.通过子类序列化父类

    <?php
    
    class Base implements Serializable{
        private $data;
    
        public function __construct( $data ) {
            $this->data = $data;
        }
    
        public function getData() {
            return $this->data;
        }
    
        public function serialize() {
            return serialize( $this->data );
        }
    
        public function unserialize( $serialize ) {
            $this->data = unserialize( $serialize );
        }
    }
    
    class Sub extends Base{
        private $id;
        private $name;
    
        public function __construct( $id, $name, $data ) {
            parent::__construct( $data );
            $this->id = $id;
            $this->name = $name;
        }
    
        public function serialize() {
            return serialize(
                array(
                    "id" => $this->id,
                    "name" => $this->name,
                    "parentData" => parent::serialize()  //注意这里
                )
            );
        }
    
        public function unserialize( $serialize ) {
            $temp = unserialize( $serialize );
            $this->id = $temp["id"];
            $this->name = $temp["name"];
            parent::unserialize( $temp["parentData"] );
        }
    
        public function getVar() {
            return $this->id."|".$this->name."|".parent::getData();
        }
    }
    
    $instance = new Sub( 12, "lee", "hello world" );
    $serialized = serialize( $instance );
    echo $serialized."
    ";
    $unserialized = unserialize( $serialized );
    echo $unserialized->getVar();
    
    //echo
    //C:3:"Sub":86:{a:3:{s:2:"id";i:12;s:4:"name";s:3:"lee";s:10:"parentData";s:19:"s:11:"hello world";";}}
    //12|lee|hello world

    3.子类不用重写父类serialize方法也能序列化自身的变量,用get_object_vars()函数配合。

    <?php
    
    class Pot implements Serializable
    {
        protected $_a;
        protected $_b;
    
        public function serialize() {
            return serialize( get_object_vars( $this ) );
        }
        public function unserialize( $data ) {
            $values = unserialize( $data );
            foreach ( $values as $key=>$value ) {
                $this->$key = $value;
            }
        }
    }
    
    //And now one descendant:
    
    class PotId extends Pot
    {
        protected $_k;
    }
    
    class Pots extends PotId
    {
        protected $_l;
    }
    
    $pots = new Pots();
    
    echo serialize( $pots );
    
    //echo
    //C:4:"Pots":50:{a:4:{s:2:"_l";N;s:2:"_k";N;s:2:"_a";N;s:2:"_b";N;}}

    4.为了防止通过unserialize得到对象,可以在serialize方法中return NULL,这将放回一种序列化后的NULL。

    <?php
    
    class testNull implements Serializable{
        public function serialize() {
            return NULL;
        }
        public function unserialize($serialized) {
    
        }
    }
    
    $instance = new testNull();
    $serialized = serialize($instance);
    echo $serialized;  //N;
  • 相关阅读:
    Java面向对象---重写(Override)与重载(Overload)
    Java面向对象---继承
    Java 异常处理
    Java 正则表达式
    Java 日期时间
    Java Number & Math 类
    Java StringBuffer 和 StringBuilder 类
    使用老毛桃安装Windows操作系统
    Horizon代码的层次结构
    云平台-资源监控模块和分布式日志采集系统模块
  • 原文地址:https://www.cnblogs.com/leezhxing/p/4286793.html
Copyright © 2020-2023  润新知