php中的序列化

简介

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


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)
NULL
array(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)
}
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值