1 背景
在PHP中,每个类的定义都以关键字 class 开头,后面跟着类名,后面跟着一对花括号,里面包含有类的属性与方法的定义。 一个类可以包含有属于自己的属性(常量,变量)和方法(函数)。 由于类的实例化对象比较抽象,不方便用于传输和存储。
2 定义
序列化与反序列化过程在php、python等多种语言中普遍存在。 序列化:程序将对象状态转换为字节序列的过程(即将对象状态转换为可存储或可传输的过程)。 反序列化:程序把存储或传输的字节序列恢复为对象的过程。 核心思想:对象状态的保存和重建。
3 作用及优点
序列化的意义:在传递和保存对象时,为保证对象的完整性和可传递性,程序将对象转换为有序字节流,以便在网络上传输或者保存在本地文件中。 反序列化的意义:根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。 优点:
将对象转为字节流存储到硬盘上,当JVM停机的话,字节流还会在硬盘上默默等待,等待下一次JVM的启动,把序列化的对象,通过反序列化为原来的对象。 序列化后的二进制序列能够减少存储空间(永久性保存对象)。 序列化成字节流形式的对象可以进行网络传输。 通过序列化可以在进程间传递对象。
4 例子:测试php代码中序列化与反序列化执行过程
4.1 测试环境
服务器:在虚拟机中安装win2008及phpstudy,参考《win2008R2SP1+WAMP环境部署 》。 客户端:真实机浏览器。
4.2 测试序列化过程
在服务器根目录下新建一个txt文件,输入以下内容,并重命名为test.php。
< meta charset = "utf-8" >
< ? php
class stu {
public $name ;
public $sex ;
public $age ;
public $score ;
}
$stu1 = new stu ( ) ;
$stu1 -> name = 'libai' ;
$stu1 -> sex = true ;
$stu1 -> age = 18 ;
$stu1 -> score = 66.6 ;
echo "采用echo输出:<br>" ;
echo $stu1 ;
echo '<hr>' ;
echo "采用var_dump输出<br>" ;
var_dump ( $stu1 ) ;
echo '<hr>' ;
echo "序列化后采用echo输出<br>" ;
echo serialize ( $stu1 ) ;
? >
真实机浏览器访问该网页,显示如下,表示第20行输出出错,程序终止。 将上述代码的19~21行注释掉,再次访问,显示如下。 可以看到对象被序列化成字符串:,其中:
O表示该字符串对对象;3表示该对象名有3个字符;stu表示对象名;4表示有4个属性; 花括号内每两个分号表示一个属性的键值对。
O : 3 : "stu" : 4 : { s: 4 : "name" ; s: 5 : "libai" ; s: 3 : "sex" ; b: 1 ; s: 3 : "age" ; i: 18 ; s: 5 : "score" ; d: 66.599999999999994 ; }
4.3 测试反序列化过程
将上述test.php文件内容修改如下:
< meta charset = "utf-8" >
< ? php
class stu {
public $name ;
public $sex ;
public $age ;
public $score ;
}
$obj = $_GET [ 'obj' ] ;
$stu1 = unserialize ( $obj ) ;
echo "采用var_dump输出<br>" ;
var_dump ( $stu1 ) ;
echo '<hr>' ;
echo "序列化后采用echo输出<br>" ;
echo serialize ( $stu1 ) ;
? >
真实机浏览器访问该网页并传入参数obj,访问参数为?obj=O:3:%22stu%22:4:{s:4:%22name%22;s:5:%22libai%22;s:3:%22sex%22;b:1;s:3:%22age%22;i:18;s:5:%22score%22;d:66.6;}
,网页显示结果如下。可以看到反序列后后成功生成对象。
5 例子:SessionID在php中的序列化与反序列化
5.1 SessionID序列化
以PHP语言为例,简单介绍Session ID序列化的过程。 在第4行中,odbc_connect 函数,执行成功则返回connection ID函数,失败则返回false。输入参数依次为数据库名、用户名、密码、其他参数。 在第5行中,odbc_prepare 函数,如果成功准备 SQL 命令,则返回 ODBC 结果标识符; 出错时返回 false。 在第6行,serialize()函数将 session_data 进行序列化;随后,array()生成一个数组,数组的第一个元素是序列化后的字节流,第二个元素是变量。 在第7行的判断条件中,odbc_execute()函数将准备好的数组传入到准备好的SQL语句中执行,进行数据库中的对应数据的更新。如果执行失败,则执行 if 函数体。
<?php
$conn = odbc_connect ( "webdb" , "php" , "chicken" ) ;
$stmt = odbc_prepare ( $conn , "UPDATE sessions SET data = ? WHERE id = ?" ) ;
$sqldata = array ( serialize ( $session_data ) , $PHP_AUTH_USER ) ;
if ( ! odbc_execute ( $stmt , & $sqldata ) ) {
$stmt = odbc_prepare ( $conn ,
"INSERT INTO sessions (id, data) VALUES(?, ?)" ) ;
if ( ! odbc_execute ( $stmt , & $sqldata ) ) {
}
}
? >
5.2 SessionID反序列化
以PHP语言为例,简单介绍Session ID反序列化的过程,是上述例子的延续。 在第6行,使用array()函数将超全局变量$_SERVER的属性PHP_AUTH_USER内容定义为数组。 在第7行中,使用odbc_execute()函数从数据库中找到对应user的SessionID;odbc_fetch_into() 返回结果中的列数,错误时为返回false。 在第12行中,对从数据库中取得的SessionID进行反序列化。
<?php
$conn = odbc_connect ( "webdb" , "php" , "chicken" ) ;
$stmt = odbc_prepare ( $conn , "SELECT data FROM sessions WHERE id = ?" ) ;
$sqldata = array ( $_SERVER [ 'PHP_AUTH_USER' ] ) ;
if ( ! odbc_execute ( $stmt , $sqldata ) || ! odbc_fetch_into ( $stmt , $tmp ) ) {
$session_data = array ( ) ;
} else {
$session_data = unserialize ( $tmp [ 0 ] ) ;
if ( ! is_array ( $session_data ) ) {
$session_data = array ( ) ;
}
}
? >
6 总结
了解序列化与反序列化的作用; 掌握PHP中序列化与反序列化的使用方法。
参考文献
《序列化和反序列化的详解 》 《PHP类与对象基本概念 》初学者建议看一下PHP官方手册对类的应用方法。