序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
在PHP中,可以通过serialize()方法序列化,serialize()返回字符串,此字符串包含了表示value的字节流,可以存储于任何地方。
这有利于存储或传递PHP的值,同时不丢失其类型和结构。
想要将已序列化的字符串变回PHP的值,可使用unserialize()方法。serialize()可处理除了resource(资源类型)之外的任何类型。甚至可以serialize()那些包含了指向其自身引用的数组。你正serialize()的数组或对象中的引用也将被存储。
当序列化对象时,PHP将试图在序列动作之前调用该对象的成员函数__sleep()。这样就允许对象在被序列化之前做任何清除操作。类似的,当使用unserialize()恢复对象时,讲调用__wakeup()成员方法。
序列化和反序列化的一些基本的解释可以移步到:点击打开链接 查看。
比如我现在链接数据库,链接数据库类的代码可以移步到:点击打开链接 查看。
我这里做一下小小的改变,加入两个魔术方法:
public function __sleep()
{
return ['host', 'username', 'password', 'dbName', 'port', 'charset'];
}
public function __wakeup()
{
$this->mysqlConnect();
}
由于没有加入到代码片段,这次还是贴出来吧,如下:
class DB {
private $host; //主机
private $username; //用户名
private $password; //密码
private $dbName; //数据库名称
private $port; //数据库端口
private $socket; //套接字
private $mysqli; //mysqli对象
private $charset; //字符集
private $lastSql; //最后执行的sql
public function __construct($array=[])
{
$this->charset = isset($array['charset']) ? $array['charset'] : 'utf8';
$this->connect($array);
$this->mysqlConnect();
}
public function connect($array=[])
{
$this->host = isset($array['host']) ? $array['host'] : '127.0.0.1';
$this->username = isset($array['username']) ? $array['username'] : 'root';
$this->password = isset($array['password']) ? $array['password'] : 'root';
$this->dbName = isset($array['dbName']) ? $array['dbName'] : '';
$this->port = isset($array['port']) ? $array['port'] : 3306;
$this->socket = isset($array['socket']) ? $array['socket'] : '';
}
private function mysqlConnect()
{
$this->mysqli = new mysqli($this->host,$this->username,$this->password,$this->dbName,$this->port);
}
public function query($sql)
{
$this->lastSql = $sql;
$result = $this->mysqli->query($this->lastSql);
if($result === false) {
$this->error();
}
return $result;
}
public function Charset($charset='')
{
$this->charset = $charset ? $charset: $this->charset;
$this->execute("set names {$this->charset}");
}
public function execute($sql)
{
$this->query($sql);
return true;
}
public function select($sql)
{
$result = $this->query($sql);
return $result->fetch_all(MYSQLI_ASSOC);
}
public function getLastSql()
{
return $this->lastSql;
}
public function error()
{
$result = '';
if($this->mysqli->error) {
$result.= "错误提示:{$this->mysqli->error}<br />";
}
if($this->mysqli->errno) {
$result.= "错误代号:{$this->mysqli->errno}<br />";
}
if(!empty($result)){
$result.="错误的sql语句:{$this->lastSql}";
}
if(!empty($result)) {
exit($result);
} else {
exit('没有错误');
}
}
public function __sleep()
{
return ['host', 'username', 'password', 'dbName', 'port', 'charset'];
}
public function __wakeup()
{
$this->mysqlConnect();
}
}
我现在实例化类,然后查询,然后如果我想把这个类传递到其他地方,其他地方拿起来就可以直接用,而不用再去实例化时候该怎么办呢?
我new一个对象出来,然后将它序列化:
$db1 = new DB(['dbName'=>'test']);
var_dump($db1->select('select * from test limit 1,3'));
$str = serialize($db1);
结果如下:
假如我这个$str,传递到我其他的页面,怎么办传递? session,cookie,文件,数据库都可以传递,我在另外的一个页面,将这个字符串反序列化:
$str = $_SESSION['str'];
$str = serialize($db1);
$db2 = unserialize($str);
var_dump($db2->select('select * from test limit 1,4'));
然后我们再看看结果:
哈哈,我们又链接成功了,主要是我们在__wakeup()方法里面做了链接操作,在这个类被反序列化的时候,就自动连上了。
不过有一点要注意,反序列化成对象的时候,其实和序列化时候的类已经不是同一个类了,我var_dump两个对象,可以看出来
对象编号已经改变了。