php中的序列化

来源:互联网 发布:磁卡充值系统java 编辑:程序博客网 时间:2024/06/07 09:00

简介

序列化就是将一个值转换为字符串,并可将字符串存入硬盘文件、数据库等。任何时候只要将这个字符串作反序列化操作,就可还原出原来的值。


serialize()
string serialize ( mixed $value )
序列化值$value,并以字符串形式返回。serialize() 可处理除了 resource 之外的任何类型。甚至可以 serialize() 那些包含了指向其自身引用的数组。你正 serialize() 的数组/对象中的引用也将被存储。

unserialize()
mixed unserialize ( string $str )
对单一的已序列化的变量进行操作,将其转换回 PHP 的值。注意,序列化得到的字符串中是包含类型信息的,所以反序列化得到的结果不需要再次执行类型转换。

正常情况下返回的是转换之后的值,可为 integer、float、string、array 或 object类型。 如果传递的字符串不可解序列化,则返回 FALSE,并产生一个 E_NOTICE。 如果反序列化了 FALSE 的值,或者在过程中发生了错误,都会返回 FALSE。 可以通过 str 和 serialize(false) 进行比较,或者捕捉 E_NOTICE 错误来判断这种特殊情况。 

$a = 78;$b = "abc";$c = true;$d = null;$e = [[1,2],[3,4]];$sa = serialize($a);$sb = serialize($b);$sc = serialize($c);$sd = serialize($d);$se = serialize($e);echo "$sa\n";   // i:78;echo "$sb\n";   // s:3:"abc";echo "$sc\n";   // b:1;echo "$sd\n";   // N;echo "$se\n";   // a:2:{i:0;a:2:{i:0;i:1;i:1;i:2;}i:1;a:2:{i:0;i:3;i:1;i:4;}}$a = unserialize($sa);$b = unserialize($sb);$c = unserialize($sc);$d = unserialize($sd);$e = unserialize($se);var_dump($a);var_dump($b);var_dump($c);var_dump($d);var_dump($e);/*int(78)string(3) "abc"bool(true)NULLarray(2) {  [0]=>  array(2) {    [0]=>    int(1)    [1]=>    int(2)  }  [1]=>  array(2) {    [0]=>    int(3)    [1]=>    int(4)  }}*/

序列化对象

序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。 所以,为了能够unserialize()一个对象,这个对象的类必须已经定义过。如果序列化类A的一个对象,将会返回一个跟类A相关,而且包含了对象所有变量值的字符串。 如果要想在另外一个文件中解序列化一个对象,这个对象的类必须在解序列化之前定义。如果在解序列化对象的时候,没有找到该对象的类的定义,将会使用__PHP_Incomplete_Class_Name作为该对象的类,导致返回一个没有用的对象。 
可以通过包含一个定义该类的文件或使用函数spl_autoload_register()来实现。 

也可以通过配置项unserialize_callback_func来实现类的自动加载:
ini_set('unserialize_callback_func', 'mycallback'); // 设置回调函数
function mycallback($classname) 
{
   // 只需包含含有类定义的文件
   // $classname 指出需要的是哪一个类
}

serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。 
注意,__sleep() 不能返回父类的私有成员的名字。可以用 Serializable 接口来替代。 
unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。 __wakeup() 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。 

class MyClass{  public $a = 5;  public $b = 6;  public $c = 7;  public function __sleep() {    return array("b");  }  public function __wakeup() {    $this->c = 0;  }}$var = new MyClass();$var->a = 555;$var->b = 666;$str = serialize($var);$var = unserialize($str);var_dump($var);/*object(MyClass)#2 (3) {  ["a"]=>  int(5)  ["b"]=>  int(666)  ["c"]=>  int(0)}*/

Serializable 序列化接口

一个类通过实现此接口,可自定义序列化和反序列化的过程,该接口包含如下两个方法:
abstract public string serialize ( void )
abstract public mixed unserialize ( string $serialized )


实现此接口的类将不再支持 __sleep() 和 __wakeup()。不论何时,只要有实例需要被序列化,serialize 方法都将被调用。它将不会调用 __destruct() 或有其他影响,除非程序化地调用此方法。当数据被反序列化时,类将被感知并且调用合适的 unserialize() 方法而不是调用 __construct()。如果需要执行标准的构造器,你应该在这个方法中进行处理。 


下例中,类在序列化时只保存了部分父类私有成员。

class Base{  private $a;  private $b;  public function __construct($a, $b) {    $this->a = $a;    $this->b = $b;  }  protected function getA() {    return $this->a;  }}class MyClass extends Base implements Serializable{  public function __construct($a, $b) {    parent::__construct($a, $b);  }  public function serialize() {    return serialize($this->getA());  }  public function unserialize($str) {    $a = unserialize($str);    parent::__construct($a, 0);  }}$var = new MyClass(5, 6);var_dump($var);$str = serialize($var);$var = unserialize($str);var_dump($var);/*object(MyClass)#1 (2) {  ["a":"Base":private]=>  int(5)  ["b":"Base":private]=>  int(6)}object(MyClass)#2 (2) {  ["a":"Base":private]=>  int(5)  ["b":"Base":private]=>  int(0)}*/

原创粉丝点击