学习记录--Day13(php序列化与反序列化的学习)

最近感觉自己学的很难受,甚至在想自己还要不要学了,一直学的没什么效果吧。。。
今天重新学一下序列化的内容吧
一、概念

  • 什么是序列化和反序列化?
  • 为什么要序列化和反序列化?
    序列化是将变量转换为可保存或传输的字符串的过程;反序列化就是在适当的时候把这个字符串再转化成原来的变量使用。这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性。
    1、常用的函数是serialize和unserialize函数
    (注意数组的输出要用print_r)
    在这里插入图片描述
    从输出可以看出,反序列化的结果种a代表数组,3代表三个变量,括号内的s表示字符串,1等数字表示变量名及变量的长度;同时可以看到反序列化的数组经过序列化回到原来的数组值

当数组值包含如双引号、单引号或冒号等字符时,它们被反序列化后,可能会出现问题。为了克服这个问题,一个巧妙的技巧是使用base64_encode和base64_decode

$a = array();
//序列化
$b = base64_encode(serialize($a)); 
//反序列化
$c = unserialize(base64_decode($b)); 

但是base64编码将增加字符串的长度。为了克服这个问题,可以和gzcompress(压缩字符串)一起使用。

function my_serialilze($a)//序列化函数
{
    return base64_encode(gzcompress(serialize($a)));
}
function my_unserialize($b)//反序列化函数
{
    return unserialize(gzuncompress(base64_decode($b)));
}

2、json_encode 和 json_decode

使用json_encode和json_decode格式输出要比serialize和unserialize格式快得多。
JSON格式是可读的。
JSON格式比serialize返回数据结果小。
JSON格式是开放的、可移植的。其他语言也可以使用它。

<?php
$a=array('a'=>'fanfan','b'=>'xixi','c'=>'abab');
echo $b=serialize($a);
echo '<br />';
echo $b1=json_encode($a);
echo '<br />';
print_r($c=unserialize($b));
echo '<br />';
print_r($c=json_decode($b1));

在这里插入图片描述
可以看到json_encode输出的长度明显要短一些
3、var_export 和 eval
var_export 函数把变量作为一个字符串输出;
eval把字符串当成PHP代码来执行,反序列化得到最初变量的内容。

echo $b2=var_export($a,true);

eval('$my_var='. $b . ';');
print_r($my_var);//这个应该不对吧,不是很明白,是有错的

在这里插入图片描述

4、wddx_serialize_value 和 wddx deserialize
wddx_serialize_value函数可以序列化数组变量,并以XML字符串形式输出。

echo $b3=wddx_serialize_value($a);
//输出结果:<wddxPacket version='1.0'><header/><data><struct><var name='a'><string>fanfan</string></var><var name='b'><string>xixi</string></var><var name='c'><string>abab</string></var></struct></data></wddxPacket>

二、php的几个魔术方法

魔术方法 如何调用
__wakeup() 当调用unserialize()函数时自动调用
__construct() 当一个类被创建时自动调用
__destruct() 当一个类被销毁时自动调用
__tostring() 当把一个类当作字符串使用时自动调用
__sleep() 当调用serialize()函数时自动调用
__invoke() 当把一个类当作函数使用时自动调用
__call() 当要调用的方法不存在或权限不足时自动调用

还有几个知识点:

__wakeup()的漏洞:如果一个类的实际属性个数小于序列化的属性个数的话,就会跳过不执行__wakeup()函数(还需要补充)
__construct()函数常用于构造方法
如果在类中定义的成员修饰符是private,则正确的序列化是%00类名%00成员名
如果在类中定义的成员修饰符是protected,则正确的序列化是%00%00成员名

1、_construct():构造函数,当类实例化时用来初始化对象或是赋初值;每次通过new运算符创建对象时自动被调用;
2、_destruct()(与_construct函数相对应):析构函数,当对象所有引用都被删除或是对象被显示销毁时,系统会自动执行析构函数;
3、与序列化直接相关的函数

  • _sleep
    当进行类序列化操作时,调用serialize()函数会先检查类种是否存在_sleep()函数,存在的话会先调用_sleep(),再执行序列化操作;_sleep()函数会返回一个数组,其中包含对象中所有应被序列化的变量名称,如果该方法未返回任何内容,则NULL被序列化,并产生一个错误。
<?php

class FAN{
    public $a;
    public $b;
    public $c;
    public function __construct($a,$b){
        $this->a = $a;
        $this->b = $b;
    }
    public function __sleep(){
        $this->c = $this->a.$this->b;
        return array('a','c');//返回了a,c,也就是下面的ver和verweb
    }

}

$c = new FAN('ver','web');
$d = serialize($c);
echo $d;//O:3:"FAN":2:{s:1:"a";s:3:"ver";s:1:"c";s:6:"verweb";}

当调用unserialize()函数时会先检查是否存在_wakeup()函数,如果存在的话,会在成功重构对象后调用_wakeup(),多用于与数据库重新建立连接上。

<?php

class FAN{
    public $a;
    public $b;
    public $c;
    public function __construct($a,$b){
        $this->a = $a;
        $this->b = $b;
    }
    public function __weakup()
    {
        $this->b = $this->a . $this->c;
    }

}
$d='O:3:"FAN":2:{s:1:"a";s:3:"ver";s:1:"c";s:6:"verweb";}';
var_dump(unserialize($d));
//object(FAN)#1 (3) {
  ["a"]=>
  string(3) "ver"
  ["b"]=>
  NULL//因为没有对a和c传参,所以是NULLS
  ["c"]=>
  string(6) "verweb"
  }

以上只是相关的简单操作,接下来会重点学习对于某些操作会出现的问题,以及剩下的几个魔术方法及其调用关系,session机制,和重新学习phar://协议

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值