PHP中的串行化变量和序列化对象


Posted in PHP onSeptember 05, 2006

串行化大概就是把一些变量转化成为字符串的字节流的形式,这样比较容易传输、存储。当然,关是传输存储没有什么,关键是变成串的形式以后还能够转化回来,而且能够保持原来数据的结构。

在PHP中有多串行化处理的函数:serialize(),该函数把任何变量值(除了资源变量)转化为字符串的形式,可以把字符串保存到文件里,或者注册为Session,乃至于使用curl来模拟GET/POST来传输变量,达到RPC的效果。

如果要将串行化的变量转化成PHP原始的变量值,那么可以使用unserialize()函数。

一、变量串行化

我们举简单的例子来说明串行化,以及它的存储格式。

整型:

$var = 23;

echo serialize($var);

输出:

i:23;

浮点型:

$var = 1.23;

echo serialize($var);

输出:

d:1.229999999999999982236431605997495353221893310546875;

字符串:

$var = "This is a string";

echo serialize($var);

$var = "我是变量";

echo serialize($var);

输出:

s:16:"This is a string";

s:8:"我是变量";

布尔型:

$var = true;

echo serialize($var);

$var = false;

echo serialize($var);

输出:

b:1;

b:0;

上面这些基本类型串行化之后的情况很清楚,串行化之后的存储格式是:

变量类型:[变量长度:]变量值;

就是第一位字符代表变量类型,第二个:代表分割,变量长度是可选的,就是在字符串类型里有,其他类型没有,最后一个就是变量值,每个串行化的值以";"作为结束。

比如我们整型数字23串行化之后就是:i:23,那么它没有长度,只有类型和变量值,i代表integer,通过冒号分割,后面保存的是整型值23,包括浮点型(双字节型)也是一样。布尔型的话,类型是b(boolean),如果是true的话,那么串行化的值是1,如果是false那么值就是0。字

符串值话中间会多一个保存的值得,保存字符串的长度值,比如字符串"This is a string",那么生成的串行化的值是 s:16:"This is a string"; s是string,代表类型,中间的16就是该字符串的长度,如果是中文的话,那么每个中文是两个字符来保存的,比如字符串 "我是变量",生成的串行化值是:s:8:"我是变量"; 就是8个字符的长度。

下面我们重点来讲一下数组变量串行化。

数组变量:

$var = array("abc", "def", "xyz", "123");
echo serialize($var);

输出:

a:4:{i:0;s:3:"abc";i:1;s:3:"def";i:2;s:3:"xyz";i:3;s:3:"123";}

就是把我的数组 $var 串行化得到的字符串值,我们的$var数组包括4个字符串元素,分别是"abc", "def", "xyz", "123",我们来分析一下串行化后的数据,为了简便起见,我们把串行化的数据列成数组的样式:

a:4:
{
i:0;s:3:"abc";
i:1;s:3:"def";
i:2;s:3:"xyz";
i:3;s:3:"123";
}

这样排列就比较清晰了,看开始的字符串:a:4:{...} 首先第一个字符a保存的是变量类型是array(数组)类型,第二个 4 保存的是数组元素的个数,一共有4个,然后在{}之间数组元素的内容。比如第一个数组元素:i:0;s:3:"abc"; i代表是当前数组元素的索引值类型是整型,并且值是 0,元素值的类型是s(字符串的),个数是 3 个,具体值是"abc",分号结束,下面的数组元素依次类推。

我们再看看使用字符串做为元素索引会如何:

$var = array("index1"=>"abc", "index2"=>"def", "index3"=>"xyz", "index4"=>"123");
echo serialize($var);

输出:

a:4:{s:6:"index1";s:3:"abc";s:6:"index2";s:3:"def";s:6:"index3";s:3:"xyz";s:6:"index4";s:3:"123";}

变成数组样式后:

a:4:
{
 s:6:"index1";s:3:"abc";
 s:6:"index2";s:3:"def";
 s:6:"index3";s:3:"xyz";
 s:6:"index4";s:3:"123";
}

其实跟上面没有太大区别,不过是开始的索引变成了保存字符串的形式,比如第一个元素:s:6:"index1";s:3:"abc";第一项就是索引值:s:6:"index1"; s是类型,6是索引字符串的长度,"index1"就是索引的值。后面的s:3:"abc"; 就是元素值,这个好理解,就不讲了。

从上面来看,我们大致了解了基本数据类型的串行化,其实我们完全可以构造自己的串行化功能,或者从这个角度去扩展,开发自己的串行化程序,便于我们的变量交换。

当然,其实我们也可以利用这个功能,把数组或者任意其他变量串行化成字符串,然后通过curl功能来模拟GET/POST功能,达到能够无用用户执行动作就从远程服务器获取数据的功能。

二、对象序列化

对象的序列化也是一个比较普遍的功能,能够把一个对象进行串行化以后变成一个字符串,能够保存或者传输。

我们先看一个例子:

class TestClass
{
 var $a;
 var $b;

 function TestClass()
 {

$this->a = "This is a";

$this->b = "This is b";
 }

 function getA()
 {

return $this->a;
 }

 function getB()
 {

return $this->b;
 }
}

$obj = new TestClass;
$str = serialize($obj);
echo $str;

输出结果:

O:9:"TestClass":2:{s:1:"a";s:9:"This is a";s:1:"b";s:9:"This is b";}

我们来分析一个对象串行化之后的字符串。

O:9:"TestClass":2:
{
 s:1:"a";s:9:"This is a";
 s:1:"b";s:9:"This is b";
}

首先看对于对象本身的内容:O:9:"TestClass":2:O是说明这是一个对象类型(object),然后9是代表对象的名字查过浓度,2是代表该对象有几个属性。在看两个属性的内容:

s:1:"a";s:9:"This is a"; 其实跟数组的内容比较类似,第一项:s:1:"a"; 是描述属性名称的,第二项s:9:"This is a"; 是描述属性值的。后面的属性类似。

先说一种对象序列化的应用,下面的内容是PHP手册上,没有更改原文。

serialize() 返回一个字符串,包含着可以储存于 PHP 的任何值的字节流表示。unserialize() 可以用此字符串来重建原始的变量值。用序列化来保存对象可以保存对象中的所有变量。对象中的函数不会被保存,只有类的名称。

要能够 unserialize() 一个对象,需要定义该对象的类。也就是,如果序列化了 page1.php 中类 A 的对象 $a,将得到一个指向类 A 的字符串并包含有所有 $a 中变量的值。如果要在 page2.php 中将其解序列化,重建类 A 的对象 $a,则 page2.php 中必须要出现类 A 的定义。这可以例如这样实现,将类 A 的定义放在一个包含文件中,并在 page1.php 和 page2.php 都包含此文件。

<?php
// classa.inc:
class A
{
 var $one = 1;

 function show_one()
 {

echo $this->one;
 }
}

// page1.php:
include("classa.inc");

$a = new A;
$s = serialize($a);
// 将 $s 存放在某处使 page2.php 能够找到
$fp = fopen("store", "w");
fputs($fp, $s);
fclose($fp);

// page2.php:
// 为了正常解序列化需要这一行
include("classa.inc");

$s = implode("", @file("store"));
$a = unserialize($s);

// 现在可以用 $a 对象的 show_one() 函数了
$a->show_one();
?>

如果在用会话并使用了 session_register() 来注册对象,这些对象会在每个 PHP 页面结束时被自动序列化,并在接下来的每个页面中自动解序列化。基本上是说这些对象一旦成为会话的一部分,就能在任何页面中出现。

强烈建议在所有的页面中都包括这些注册的对象的类的定义,即使并不是在所有的页面中都用到了这些类。如果没有这样做,一个对象被解序列化了但却没有其类的定义,它将失去与之关联的类并成为 stdClass 的一个对象而完全没有任何可用的函数,这样就很没有用处。

因此如果在以上的例子中 $a 通过运行 session_register("a") 成为了会话的一部分,应该在所有的页面中包含 classa.inc 文件,而不只是page1.php 和 page2.php。

当然,其实序列化对象其实完全可以应用在很多地方。当然,在PHP 5中对序列化的处理不一样了,我们看一下手册中的说法:

serialize() 检查类中是否有魔术名称 __sleep 的函数。如果这样,该函数将在任何序列化之前运行。它可以清除对象并应该返回一个包含有该对象中应被序列化的所有变量名的数组。

使用 __sleep 的目的是关闭对象可能具有的任何数据库连接,提交等待中的数据或进行类似的清除任务。此外,如果有非常大的对象而并不需要完全储存下来时此函数也很有用。

相反地,unserialize() 检查具有魔术名称 __wakeup 的函数的存在。如果存在,此函数可以重建对象可能具有的任何资源。

使用 __wakeup 的目的是重建在序列化中可能丢失的任何数据库连接以及处理其它重新初始化的任务。

PHP 相关文章推荐
探讨Smarty中如何获取数组的长度以及smarty调用php函数的详解
Jun 20 PHP
PHP使用DOMDocument类生成HTML实例(包含常见标签元素)
Jun 25 PHP
PHP使用ffmpeg给视频增加字幕显示的方法
Mar 12 PHP
PHP中判断文件存在使用is_file还是file_exists?
Apr 03 PHP
PHP中使用hidef扩展代替define提高性能
Apr 09 PHP
php实现转换ubb代码的方法
Jun 18 PHP
php resizeimage 部分jpg文件 生成缩略图失败的原因分析及解决办法
Mar 23 PHP
php数组冒泡排序算法实例
May 06 PHP
Apache无法自动跳转却显示目录的解决方法
Nov 30 PHP
浅谈PHP发送HTTP请求的几种方式
Jul 25 PHP
php strftime函数获取日期时间(switch用法)
May 16 PHP
PHP实现Markdown文章上传到七牛图床的实例内容
Feb 11 PHP
Windows下的PHP5.0安装配制详解
Sep 05 #PHP
PHP.MVC的模板标签系统(五)
Sep 05 #PHP
PHP.MVC的模板标签系统(四)
Sep 05 #PHP
PHP.MVC的模板标签系统(三)
Sep 05 #PHP
PHP.MVC的模板标签系统(二)
Sep 05 #PHP
PHP.MVC的模板标签系统(一)
Sep 05 #PHP
apache+mysql+php+ssl服务器之完全安装攻略
Sep 05 #PHP
You might like
文件上传程序的全部源码
2006/10/09 PHP
php抽奖小程序的实现代码
2013/06/18 PHP
php文件上传的例子及参数详解
2013/12/12 PHP
YII模块实现绑定二级域名的方法
2014/07/09 PHP
php时间函数用法分析
2016/05/28 PHP
PHP之十六个魔术方法详细介绍
2016/11/01 PHP
THINKPHP在添加数据的时候获取主键id的值方法
2017/04/03 PHP
基于jquery的一个简单的脚本验证插件
2010/04/05 Javascript
JavaScript 判断日期格式是否正确的实现代码
2011/07/04 Javascript
jQuery 无限级菜单的简单实例
2014/02/21 Javascript
JS数组合并push与concat区别分析
2015/12/17 Javascript
JavaScript SHA1加密算法实现详细代码
2016/10/06 Javascript
jQuery的ready方法实现原理分析
2016/10/26 Javascript
详解微信小程序 页面跳转 传递参数
2016/12/08 Javascript
微信小程序选择图片和放大预览图片功能
2017/11/02 Javascript
react-native 圆弧拖动进度条实现的示例代码
2018/04/12 Javascript
JavaScript常用数学函数用法示例
2018/05/14 Javascript
JS实现带阴历的日历功能详解
2019/01/24 Javascript
[08:08]2014DOTA2国际邀请赛中国区预选赛精彩TOPPLAY
2014/06/25 DOTA
[01:02:32]DOTA2-DPC中国联赛 正赛 iG vs PSG.LGD BO3 第二场 2月26日
2021/03/11 DOTA
linux系统使用python获取cpu信息脚本分享
2014/01/15 Python
Python操作列表的常用方法分享
2014/02/13 Python
python实现逻辑回归的方法示例
2017/05/02 Python
Python实现的生成格雷码功能示例
2018/01/24 Python
cmd运行python文件时对结果进行保存的方法
2018/05/16 Python
python安装和pycharm环境搭建设置方法
2020/05/27 Python
Python中logging日志的四个等级和使用
2020/11/17 Python
百度软件工程师职位
2013/02/14 面试题
Python是如何进行类型转换的
2013/06/09 面试题
PHP引擎php.ini参数优化深入讲解
2021/03/24 PHP
应届生会计求职信
2013/11/11 职场文书
编辑硕士自荐信范文
2013/11/27 职场文书
供货协议书
2014/04/22 职场文书
理财学专业自荐书
2014/06/28 职场文书
大学毕业生个人自荐书
2014/07/02 职场文书
2016大一新生军训心得体会
2016/01/11 职场文书