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 相关文章推荐
Ajax+PHP边学边练 之五 图片处理
Dec 03 PHP
一步一步学习PHP(3) php 函数
Feb 15 PHP
PHP 图像尺寸调整代码
May 26 PHP
如何在Ubuntu下启动Apache的Rewrite功能
Jul 05 PHP
PHP mysql与mysqli事务使用说明 分享
Aug 17 PHP
php中文验证码实现示例分享
Jan 12 PHP
PHP下获取上个月、下个月、本月的日期(strtotime,date)
Feb 02 PHP
windows7下安装php的imagick和imagemagick扩展教程
Jul 04 PHP
PHP使用mysql_fetch_row查询获得数据行列表的方法
Mar 18 PHP
10款实用的PHP开源工具
Oct 23 PHP
Twig模板引擎用法入门教程
Jan 20 PHP
php通过会话控制实现身份验证实例
Oct 18 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
php格式化日期实例分析
2014/11/12 PHP
基于GD2图形库的PHP生成图片缩略图类代码分享
2015/02/08 PHP
WordPress迁移时一些常见问题的解决方法整理
2015/11/24 PHP
基础的prototype.js常用函数及其用法
2007/03/10 Javascript
商城常用滚动的焦点图效果代码简单实用
2013/03/28 Javascript
Extjs407 getValue()和getRawValue()区别介绍
2013/05/21 Javascript
运用JQuery的toggle实现网页加载完成自动弹窗
2014/03/18 Javascript
JQuery实现的购物车功能(可以减少或者添加商品并自动计算价格)
2015/01/13 Javascript
浅谈angular.js中实现双向绑定的方法$watch $digest $apply
2015/10/14 Javascript
JavaScript的Number对象的toString()方法
2015/12/18 Javascript
微信小程序 天气预报开发实例代码源码
2017/01/20 Javascript
JavaScript 日期时间选择器一些小结
2018/04/02 Javascript
Vue 无限滚动加载指令实现方法
2019/05/28 Javascript
element-ui table行点击获取行索引(index)并利用索引更换行顺序
2020/02/27 Javascript
基于JQuery和DWR实现异步数据传递
2020/10/16 jQuery
vue3.0中setup使用(两种用法)
2020/12/02 Vue.js
Python3读取zip文件信息的方法
2015/05/22 Python
在Python中使用zlib模块进行数据压缩的教程
2015/06/26 Python
Python的Flask开发框架简单上手笔记
2015/11/16 Python
Python中的字符串类型基本知识学习教程
2016/02/04 Python
PyQt5每天必学之布局管理
2018/04/19 Python
替换python字典中的key值方法
2018/07/06 Python
使用python去除图片白色像素的实例
2019/12/12 Python
Python+OpenCV实现将图像转换为二进制格式
2020/01/09 Python
Django高并发负载均衡实现原理详解
2020/04/04 Python
使用ITK-SNAP进行抠图操作并保存mask的实例
2020/07/01 Python
美国购车网站:TrueCar
2016/10/19 全球购物
Kusmi茶美国官网:优质散叶茶和茶包
2019/10/13 全球购物
利用指针变量实现队列的入队操作
2012/04/07 面试题
Python里面如何实现tuple和list的转换
2012/06/13 面试题
高校生生产实习自我鉴定
2013/09/21 职场文书
一夜的工作教学反思
2014/02/08 职场文书
大学生评语大全
2014/04/18 职场文书
西柏坡导游词
2015/02/05 职场文书
经典格言警句:没有热忱,世间便无进步
2019/11/13 职场文书
Win10此设备不支持接收Miracast无法投影的解决方法
2022/07/07 数码科技