PHP 序列化

本文最后更新于:2024年3月18日 凌晨

PHP 序列化

  • 序列化(serialztion,也称串行化)一个对象是指将一个对象转换成字节流的形式,这样就可以将对象保存在文件中,这对于数据的持久化很有用,例如,PHP session自动保存和恢复对象。
  • PHP中的序列化几乎是全自动的,除了调用serialize()unserialize(),你几乎不需要做任何额外的工作:
1
2
$encoded = serialize(something);
$something = unserialize(encoded);
  • 序列化最常用于PHP的session中,Session会为你处理好序列化,你只需要告诉PHP要跟踪哪些变量即可,并且当你的站点被访问时,它们会被自动保存,但是session并不是序列化唯一的的用武之地,如果你要实现自己的持久化对象,函数serialize()unserialize()会是很自然的选择。
  • 反序列化之前,一个对象的类必须被定义,如果尝试对一个未定义类的对象进行反序列化将会使该对象转入stdClass,从而失去作用(因为stdClass是个空对象,没有任何属性和方法),一个实际的结论是:如果你使用session对对象进行序列化和反序列化操作,就必须在站点的每个页面中包含对象的类定义的文件,例如,你的页面可能这样开始:
1
2
3
4
5
<?php
include('object_definitions.inc');// 载入对象定义。
session_start(); // 载入持久化的变量(包括对象)
?>
<html>...
  • 在序列化和反序列化的过程中,PHP有两个用于对象的钩子(hook):__sleep()__wakeup(),这两个方法用来通知对象它们是在被序列化还是反序列化,没有这些方法的对象可以被序列化,但是不会被告知序列化的过程。
  • __sleep()方法在一个对象被序列化之前被调用,它能执行一些必要的清理工作来保存对象的状态,如关闭数据库连接,写出未保存的持久性数据等,该方法将返回一个数组,其中包含那些需要被写入字节流的数据成员的名称,如果你返回了一个空数组,则说明没有任何数据被写入字节流。
  • 相反地,__wakeup()方法是在一个对象从字节流中被创建时即立即调用,这个方法将执行一些必须操作,如重新连接数据库或其他的初始化工作。
  • 下例是一个对象类:Log和,它提供了两种有用的方法:write()往一个日志文件中追加一条记录,read()读取日志文件中的当前内容,这个类使用__wakeup()来重新打开日志文件,用__sleep()关闭日志文件。

示例6-3:The Log.inc file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
class Log{
var $filename;
var $fp;

function Log($filename){
$this->filename = $filename;
$this->open();
}
function open(){
$this->fp = fopen($this->filemane,"a") or die("Can't open {$this->filename}");
}
function write($note){
fwrite($this->fp,"$note\n");
}
function read(){
return join(' ',file($this->filename));
}
function _ _wakeup(){
$this->open();
}
function _ _sleep(){
fclose($this->fp);// 关闭文件。
return array('filename');
}
}
?>
  • 在文件Log.inc中存放Log类定义,下例中的HTML页面使用Log类和session创建了一个持久性的日志变量$L

示例6-4:front.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
include_once('Log.inc');
session_start();
?>
<html><head><title>Front Page</title></head>
<body>
<?php
$now = strftime("%c");
if(!session_is_registered('L')){
$L = new Log("/tmp/persistent_log");
session_register('L');
$L->write("Created $now");
echo("Create session and persistent log object.<p>");
}
$L->write("Viewed first page $now");
echo "The log contains:<p>";
echo n12br($L->read());
?>
<a href="next.php">Move to the next page</a>
</body></html>
  • 下例展示了next.php这是一个HTML页面,随着前面一页到本页的链接,将会触发持久性对象$L的载入,_ _wakeup()重新打开日志文件,从而使对象可用。
  • 示例6-5:next.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
include_once('Log.inc');
session_start();
?>
<html><head><title>Next Page</title></head>
<body>

<?php
$now = strftime("%c");
$L->write("Viewed page 2 at $now");
echo "The log contains:<p>";
echo n12br($L->read());
?>

</body></html>

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!