php 序列化与反序列化

简介

  • 在php中,序列化用与存储或传递php的值的过程,同时不丢失其结构和数据类型。
  • 相关的函数包括serializeunserialize,魔术方法包括__sleep__wakeup

序列化

  • 语法:string serialize ( mixed $value )
  • 可以对StringIntegerBooleanNullArrayObject进行操作

反序列化

  • 语法:mixed unserialize ( string $str )
  • 如果传递的字符串不可解序列化,则返回 FALSE,并产生一个E_NOTICE
  • 返回的是转换之后的值,可为integerfloatstringarrayobject
  • 若被反序列化的变量是一个对象,在成功重新构造对象之后,PHP会自动地试图去调用__wakeup()魔术方法(如果存在的话)

演示

序列化

  1. 例一
class User {
	public $name;
	private $male;
	protected $money = 1000;

	public function __construct($data, $male) {
		$this->data = $data;
		$this->male = $male;
	}
}
$number = 66;
$str = 'jerry';
$bool = true;
$null = NULL;
$arr = array('a' => 1, 'b' => 2);
$user = new User('tom', true);

var_dump(serialize($number));
var_dump(serialize($str));
var_dump(serialize($bool));
var_dump(serialize($null));
var_dump(serialize($arr));
var_dump(serialize($user));

输出结果

string(5) "i:66;" 
string(12) "s:5:"jerry";" 
string(4) "b:1;" 
string(2) "N;" 
string(30) "a:2:{s:1:"a";i:1;s:1:"b";i:2;}" 
string(93) "O:4:"User":4:{s:4:"name";N;s:10:"Usermale";b:1;s:8:"*money";i:1000;s:4:"data";s:3:"tom";}"

注:序列化对象时,不会保存常量的值。对于父类中的变量,则会保留。

  1. 例二(对象序列化自定义)
  • 当调用serialize()函数序列化对象时,该函数会检查类中是否存在一个魔术方法__sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。可以通过重载这个方法,从而自定义序列化行为。
class User {
    const SITE = 'harry';

    public $username;
    public $nickname;
    private $password;

    public function __construct($username, $nickname, $password) {
        $this->username = $username;
        $this->nickname = $nickname;
        $this->password = $password;
    }

    // 重载序列化调用的方法
    public function __sleep() {
        // 返回需要序列化的变量名,过滤掉password变量
        return array('username', 'nickname');
    }
}
$user = new User('spike', 'kk', '123456');
var_dump(serialize($user));

输出结果(忽略了 password 字段的值):

string(66) "O:4:"User":2:{s:8:"username";s:5:"spike";s:8:"nickname";s:2:"kk";}"

反序列化

class User {
    const SITE = 'harry';

    public $username;
    public $nickname;
    private $password;

    public function __construct($username, $nickname, $password) {
        $this->username = $username;
        $this->nickname = $nickname;
        $this->password = $password;
    }

    // 定义反序列化后调用的方法
    public function __wakeup() {
        $this->password = $this->username;
    }
}
$user = 'O:4:"User":2:{s:8:"username";s:5:"spike";s:8:"nickname";s:2:"kk";}';
var_dump(unserialize($user));

输出结果:

object(User)#1 (3) { 
["username"]=> string(5) "spike" 
["nickname"]=> string(2) "kk" 
["password":"User":private]=> string(5) "spike" 
}
  • __wakeup()函数在对象被构建以后执行,所以$this->password的值不为空
  • 反序列化时,会尽量将变量值进行匹配并复制给序列化后的对象

结束

  • 反序列化时,没有定义相关的类,反序列化正常执行,得到的对象是__PHP_Incomplete_Class,这个时候我们去使用这个反序列化后的不明对象,则会抛出E_NOTICE
  • 序列化和反序列化一般用做缓存,比如session缓存,cookie等。
  • 使用json来实现对象和字符串之间的转换,在PHP中显得更加直观和轻便。而且经过测试,使用json_encode()比serialize()方法更加快速,大概快2~3倍。

你可能感兴趣的:(php)