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 相关文章推荐
简单的过滤字符串中的HTML标记
Dec 25 PHP
php字符串截取中文截取2,单字节截取模式
Dec 10 PHP
PHP的autoload机制的实现解析
Sep 15 PHP
PHP中的str_repeat函数在JavaScript中的实现
Sep 16 PHP
php后门URL的防范
Nov 12 PHP
PHP eval函数使用介绍
Dec 08 PHP
PHP文件读取功能的应用实例
May 08 PHP
PHP使用pear实现mail发送功能 windows环境下配置pear
Apr 15 PHP
浅谈php处理后端&接口访问超时的解决方法
Oct 29 PHP
php事务回滚简单实现方法示例
Mar 28 PHP
PHP实现下载远程图片保存到本地的方法
Jun 19 PHP
php apache开启跨域模式过程详解
Jul 08 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
PHILIPS L4X25T电路分析和打理
2021/03/02 无线电
基于Codeigniter框架实现的student信息系统站点动态发布功能详解
2017/03/23 PHP
javascript 循环读取JSON数据的代码
2010/07/17 Javascript
快速排序 php与javascript的不同之处
2011/02/22 Javascript
删除条目时弹出的确认对话框
2014/06/05 Javascript
jQuery实用函数用法总结
2014/08/29 Javascript
基于jquery实现轮播特效
2016/04/22 Javascript
基于Vue.js实现数字拼图游戏
2016/08/02 Javascript
Angularjs结合Bootstrap制作的一个TODO List
2016/08/18 Javascript
JS获取中文拼音首字母并通过拼音首字母快速查找页面内对应中文内容的方法【附demo源码】
2016/08/19 Javascript
深入解析js轮播插件核心代码的实现过程
2017/04/14 Javascript
jQuery列表检索功能实现代码
2017/07/17 jQuery
jQuery获取复选框选中的当前行的某个字段的值
2017/09/15 jQuery
基于jquery实现五星好评
2017/11/18 jQuery
ESLint 是如何检查 .vue 文件的
2020/11/30 Vue.js
python字符串排序方法
2014/08/29 Python
Python实现获取操作系统版本信息方法
2015/04/08 Python
Python实现完整的事务操作示例
2017/06/20 Python
详解python中的 is 操作符
2017/12/26 Python
Python内置random模块生成随机数的方法
2019/05/31 Python
python pandas写入excel文件的方法示例
2019/06/25 Python
python中pivot()函数基础知识点
2021/01/03 Python
HTML5 canvas标签实现刮刮卡效果
2015/04/24 HTML / CSS
澳大利亚游乐场设备品牌:Lifespan Kids
2019/05/24 全球购物
中国包裹转运寄送国际服务:Famiboat
2019/07/24 全球购物
物业管理应届生求职信
2013/10/28 职场文书
党校培训思想汇报
2014/01/03 职场文书
吃空饷专项治理工作实施方案
2014/03/04 职场文书
大学生社团活动总结
2014/04/26 职场文书
学校运动会霸气口号
2014/06/07 职场文书
党支部创先争优承诺书
2014/08/30 职场文书
2014党员学习习主席讲话思想汇报
2014/09/15 职场文书
公安机关纪律作风整顿个人剖析材料材料
2014/10/10 职场文书
2014年为民办实事工作总结
2014/12/20 职场文书
python中pandas.read_csv()函数的深入讲解
2021/03/29 Python
muduo TcpServer模块源码分析
2022/04/26 Redis