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>
|