反序列化,正好相反。
这里总结下最近用到的PHP里面的序列化、反序列化相关的知识。
1、serialize序列化 unserialize反序列化
php中提供了serialize函数用于将一个变量值序列化为字符串形式,
通过unserialize又可以将这个字符串反序列化为一个具体的变量值。
参考如下代码:
输出结果:$a = 1;
$sa = serialize($a);
$b = 'asarea';
$sb = serialize($b);
$c = array(0 => 1, 1 => 'asarea', 'k' => true);
$sc = serialize($c);
echo "$sa<br>$sb<br>$sc";
大致可以看出些php序列化的方式,i代表int,s代表string,a代表array。i:1;
s:6:"asarea";
a:3:{i:0;i:1;i:1;s:6:"asarea";s:1:"k";b:1;}
关于自定义class对象的序列化,参考下面代码:
输出结果:class Girl {
public $beautiful;
public function Girl($beautiful) {
$this->beautiful = $beautiful;
}
public function echoBeauty() {
echo 'i\'m' . (!$this->beautiful ? ' not ' : ' ') . 'beautiful';
}
}
$girl = new Girl(true);
// $girl->echoBeauty();
$sgirl = serialize($girl);
echo "$sgirl<br>";
$cloneGirl = unserialize($sgirl);
$cloneGirl->echoBeauty();
关于对象的反序列化,需要在反序列化处能够找到类的定义。O:4:"Girl":1:{s:9:"beautiful";b:1;}
i'm beautiful
2、json_encode与json_decode
跟serialize差不多,只不过是转化为json格式字符串。
3、var_export、var_dump、print_r
var_export用于生成一个变量的php代码表示,合法的php代码。
var_dump用于打印输出变量信息,信息全面,格式优美。
print_r用于打印输出变量易于理解的信息,信息简单。
打印结果:$c = array(0 => 1, 1 => 'asarea', 'k' => true);
var_export($c);
var_dump($c);
print_r($c);
echo "<br><br>------------<br><br>";
//对于上例中的girl
var_export($girl);
var_dump($girl);
print_r($girl);
4、evalarray ( 0 => 1, 1 => 'asarea', 'k' => true, )
array (size=3)
0 => int 1
1 => string 'asarea' (length=6)
'k' => boolean true
Array ( [0] => 1 [1] => asarea [k] => 1 )
------------
Girl::__set_state(array( 'beautiful' => true, ))
object(Girl)[1]
public 'beautiful' => boolean true
Girl Object ( [beautiful] => 1 )
相信很多人都知道这玩意,很多语言都有的,将一个字符串解析成一段代码并执行。
php也不例外,提供了这个函数。上面介绍的var_export的出来的字符串,就可以用eval执行生成变量值(相当于反序列化)。
参考下面代码:
输出$c = array(0 => 1, 1 => 'asarea', 'k' => true);
$export = var_export($c, true);
eval("\$copy = $export;");
var_dump($copy);
array (size=3)
0 => int 1
1 => string 'asarea' (length=6)
'k' => boolean true
在使用eval时,需要注意由php的开始、结束标签导致的错误。
参考下面的代码:
这段代码运行会报错,为啥?<?php
$str = "<?php \$site = 'asarea'; ?>";
eval($str);
echo $site;
?>
很简单,我们可以简单的把上述代码看成
标记嵌套了可不会报错吗。<?php
<?php $site = 'asarea'; ?>
echo $site;
?>
上例可以简单的改为
说到这个,就要说起php的开始标记<?php与结束标记?>。<?php
$str = "<?php \$site = 'asarea'; ?>";
eval("?>$str<?php ");
echo $site;
?>
//相当于
<?php
?><?php $site = 'asarea'; ?><?php
echo $site;
?>
5、php代码与html的分离
php通常是嵌入在html中的,php解析器在遇到结束标记后,会将结束标记?>与下一次开始标记<?php 之间的内容(通常是html代码)原样echo输出,参考下列代码:
可以看到该段代码的opcode如下:<?php
$a = 1;
?>
<div id='foot'>copyright asarea.me</div>
<?php
echo $a;
?>
也就是说上述html代码等同于
echo "<div id='foot'>copyright asarea.me</div>";
由此,我们可以引申出更高级的php代码嵌入方式
上述代码的opcode为:<?php
$isMobile = true;
if($isMobile) {
?>
<div id='mobile_foot'>copyright asarea.me</div>
<?php
}
else {
?>
<div id='foot'>copyright asarea.me</div>
<?php
}
?>
以上方式,对于写大块的html代码分支时,相当有用,不用再人肉去拼php字符串并echo了。