之前一直觉得php的序列化对象,只是将对象的public 变量序列化并保存。

还大言不惭的给公司同事们讲了json方式保存和传输php对象。

其实 webservice 传输对象和对象的保存 的 思路还是很值得肯定的。ios中objective-c的编译就是直接编译成一个对象保存到文件的。

以下是查到的相关资料:

    • *4.2.对象的序列化

对象(object)通常被序列化为:</p>

 
O::""::{...}

其中 表示对象的类名 的字符串长度。 表示对象中的字段1个数。这些字段包括在对象所在类及其祖先类中用 var、public、protected 和 private 声明的字段,但是不包括 static 和 const 声明的静态字段。也就是说只有实例(instance)字段。

、……表示每个字段的字段名,而 、…… 则表示与字段名所对应的字段值。

字段名是字符串型,序列化后格式与字符串型数据序列化后的格式相同。

字段值可以是任意类型,其序列化后的格式与其所对应的类型序列化后的格式相同。

    • *对象的序列化 可以保存“ 对象所在类及其祖先类中用 var、public、protected 和 private 声明的字段,但是不包括 static 和 const 声明的静态字段”

以下是做的一个小实验代码:</p>

<?php
 
 
class m{
  private $a="siyou";
  public $b="gongyong";
  protected $c="baohu";
  public $d;
  function abc(){
    echo "gan~\
";
  }
}
 
 
class h{
  public $j="h-j-public";
}
 
$x=new m();
$x->d=new h();
 
echo $l=serialize($x);
echo "\
";
print_r($c=unserialize($l));
echo $c->abc();
print_r($x);
?>

最后的输出 :

li:php dawei$ php abc.php
O:1:"m":4:{s:4:"ma";s:5:"siyou";s:1:"b";s:8:"gongyong";s:4:"*c";s:5:"baohu";s:1:"d";O:1:"h":1:{s:1:"j";s:10:"h-j-public";}}m Object([a:m:private] =&gt; siyou
[b] =&gt; gongyong[c:protected] =&gt; baohu[d] =&gt; h Object([j] =&gt; h-j-public))gan~mObject([a:m:private] =&gt; siyou[b] =&gt; gongyong[c:protected] =&gt; baohu[d] =&gt; h Object([j] =&gt; h-j-public))

可以看出, 对象序列化可以完全保存,和完全展开。

思考:

如果对象某属性=自己,该对象序列化会是什么?

<?php
 
 
class obj{
  public $s;
  public $test="999";
}
 
$newobj=new obj();
$newobj->s=$newobj;
echo serialize($newobj);
?>

输出结果:

$php test.php
O:3:"obj":2:{s:1:"s";r:1;s:4:"test";s:3:"999";}

可以看到 s:1:”s”;r:1; 这个地方有个r 表示另一种类型的格式(其实是reference的意思)。 到底什么格式呢?

    • *总结: PHP 对不同类型的数据用不同的字母进行标示,Yahoo 开发网站提供的 Using Serialized PHP with Yahoo! Web Services 一文中给出所有的字母标示及其含义</p>
a - array
b - boolean
d - double
i - integer
o - common object
r - reference
s - string
C - custom object
O - class
N - null
R - pointer reference
U - unicode string

N 表示的是 NULL,而 b、d、i、s 表示的是四种标量类型,目前其它语言所实现的 PHP 序列化程序基本上都实现了对这些类型的序列化和反序列化,不过有一些实现中对 s (字符串)的实现存在问题。

a、O 属于最常用的复合类型,大部分其他语言的实现都很好的实现了对 a 的序列化和反序列化,但对 O 只实现了 PHP4 中对象序列化格式,而没有提供对 PHP 5 中扩展的对象序列化格式的支持。

r、R 分别表示对象引用和指针引用,这两个也比较有用,在序列化比较复杂的数组和对象时就会产生带有这两个标示的数据,后面我们将详细讲解这两个标示,目前这两个标示尚没有发现有其他语言的实现。

C 是 PHP5 中引入的,它表示自定义的对象序列化方式,尽管这对于其它语言来说是没有必要实现的,因为很少会用到它,但是后面还是会对它进行详细讲解的。

U 是 PHP6 中才引入的,它表示 Unicode 编码的字符串。因为 PHP6 中提供了 Unicode 方式保存字符串的能力,因此它提供了这种序列化字符串的格式,不过这个类型 PHP5、PHP4 都不支持,而这两个版本目前是主流,因此在其它语言实现该类型时,不推荐用它来进行序列化,不过可以实现它的反序列化过程。在后面我也会对它的格式进行说明。

最后还有一个 o,这也是我唯一还没弄清楚的一个数据类型标示。这个标示在 PHP3 中被引入用来序列化对象,但是到了 PHP4 以后就被 O 取代了。在 PHP3 的源代码中可以看到对 o 的序列化和反序列化与数组 a 基本上是一样的。但是在 PHP4、PHP5 和 PHP6 的源代码中序列化部分里都找不到它的影子,但是在这几个版本的反序列化程序源代码中却都有对它的处理,不过把它处理成什么我还没弄清楚。因此对它暂时不再作更多说明了。