`

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

 
阅读更多

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

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

在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手册上,没有更改原文。
(http://www.php.net/manual/zh/language.oop.serialization.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中对序列化的处理不一样了,我们看一下手册中的说法:
http://php.liukang.com/manual/zh/function.serialize.php
http://www.php.net/manual/zh/language.oop.magic-functions.php

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

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

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

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

关于php 5的对象串行化,请参考 Haohappy 翻译的PHP5面向对象编程中的《对象串行化》:http://www.phpe.net/articles/407.shtml

文章中有不正确之处,敬请指正。

参考文档:
http://php.liukang.com/manual/zh/function.serialize.php
http://php.liukang.com/manual/zh/function.unserialize.php
http://www.php.net/manual/zh/language.oop.magic-functions.php


heiyeluren
2005/11/07


分享到:
评论

相关推荐

    对象序列化 串行化

    对象序列化 串行化 实现java对象的保存

    java对象的串行化

    我也是从网上下的,分享下,觉得有用的就下把,对象串行化的基础知识

    C#图形对象的串行化实例

    C#图形对象的串行化实例

    收集几个 MFC串行化数据和C++对象的 实例

    收集几个 MFC串行化数据和C++对象的 实例 收集几个 MFC串行化数据和C++对象的 实例

    java串行化详细的介绍了java串行化的概念

    java串行化,详细的介绍了java串行化的概念,帮助我们理解。

    C# 类序列化 文件数据库 串行化

    该程序主要应用类的序列化的知识,实现将程序中存储大量数据的实体类或结构序列化到本地磁盘。当需要时再将本地序列化的类还原到程序中去。并且应用该技术实现了文件的快速拷贝,大规模数据的存储。

    二进制BinaryFormatter进行序列化与反序列化

    .NET框架提供了两种种串行化的方式:1、是使用BinaryFormatter进行串行化;2、使用XmlSerializer进行串行化。第一种方式提供了一个简单的二进制数据流以及某些附加的类型信息,而第二种将数据流格式化为XML存储。 ...

    PHP串行化与JSON

    串行化的提出,有效的解决了对象的保存和传输的问题,举例来说,我在JavaScript中建立了一个对象,我现在想将这个对象保存到服务器端的数据库中,那么我如何进行操作呢,这个时候往往就用到了对象的串行化。...

    详解PHP对象的串行化与反串行化

    1.serialize(对象名) 将指定的类对象串行化 $str=serialize($per) //将per对象串行化,结果返回给$str 2.unserialize(串行化后的返回值) 返回结果是对象 $per=unserialize($str); 局部串行化 3.__sleep() 串行化某...

    Java 串行化(序列化)Serializable/Externalizable

    NULL 博文链接:https://zhycaf.iteye.com/blog/982092

    C# 对象串行化输入输出 演示代码

    C# 对象串行化输入输出 演示代码 C#对象串行化输入输出演示代码,载入BMP位图,输出格式为.ser的文件,有空好好研究一下。

    串行化和图像读取显示

    串行化 图像显示 串行化 图像显示VC++图像编程小软件作业编程参考

    串行化和反串行化

    串行化是指存储和获取磁盘文件、内存或其他地方中的对象。在串行化时,所有的实例数据都保存到存储介质上, 在取消串行化时,对象会被还原,且不能与其原实例区别开来。只需给类添加Serializable属性,就可以实现...

    深入理解C#序列化与反序列化的详解

    在我们深入探讨C#序列化和反序列化之前我们先要明白什么是序列化,它又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制。序列化就是把一个对象保存到一个文件或数据库字段中去,反序列化就是在适当的...

    Java关键字Transient与串行化

    关于Java中关键字transient和串行化的简略介绍

    串行化(Serialization)示范例子

    串行化是微软提供的用于对对象进行文件I/O的一种机制,该机制在框架(Frame)/文档(Document)/视图(View) 模式中得到了很好的应用。很多人对什么是串行化、怎么使对象具有串行化能力和如何使用串行化功能等问题都 不甚...

    mfc 串行化的简单使用

    简单介绍串行化的使用(即序列化),在保存文件格式的时候较实用,方便,适合mfc初学者

    串行序列信号延时测试系统

    由本测试系统送出一串串行序列信号,该串行序列信号送出后经过线路传输产生一定时间的延迟再返回到本系统,系统收到信号后判断是否为本系统发送的信号,若是,则同时测量出信号在传输过程中延迟的时间并显示出来

    tsdf.zip_tsdf_串行化

    串行化是微软提供的用于对对象进行文件I/O的一种机制,该机制在框架(Frame)/文档(Document)/视图(View) 模式中得到了很好的应用。很多人对什么是串行化、怎么使对象具有串行化能力和如何使用串行化功能等问题都 不甚...

    C#344-对象串行化源代码

    C#344-对象串行化源代码

Global site tag (gtag.js) - Google Analytics