在 PHP 进行序列化时会用到__sleep()和__wakeup()这两个构造函数.
序列化即将一个变量或者一个对象转换成字节流的过程. 序列化有效的解决了对象的保存和传输问题, 例如:在使用 session 并使用了 session_register() 函数来注册对象, 这些对象会在每个 PHP 页面结束时被自动序列化, 并在接下来的每个页面中自动解序列化, 这样在每个 PHP 页面中都可以使用这些对象
01 | //整型 |
02 | $var
= 23; |
03 | echo
serialize($var)."\n"; //i:23;
|
04 | |
05 | //浮点型 |
06 | $var
= 1.23; |
07 | echo
serialize($var)."\n"; //d:1.229999999999999982236431605997495353221893310546875; |
08 | |
09 | //字符串 |
10 | $var
= "This is a string"; |
11 | echo
serialize($var)."\n"; //s:16:"This is a string";
|
12 | |
13 | //布尔型 |
14 | $var
= true; |
15 | echo
serialize($var)."\n"; //b:1;
|
16 | |
17 | //数组变量 |
18 | $var
= array("abc","def",
"xyz","123");
|
19 | echo
serialize($var)."\n"; //a:4:{i:0;s:3:"abc";i:1;s:3:"def";i:2;s:3:"xyz";i:3;s:3:"123";} |
20 | |
21 | $var
= array("index1"=>"abc","index2"=>"def","index3"=>"xyz","index4"=>"123"); |
22 | echo
serialize($var)."\n"; //a:4:{s:6:"index1";s:3:"abc";s:6:"index2";s:3:"def";s:6:"index3";s:3:"xyz";s:6:"index4";s:3:"123";} |
23 | |
24 | //对象序列化 |
25 | class
A{ |
26 | public$a
= "a string"; |
27 | public$b
= 123; |
28 | public$c
= 123.12; |
29 | } |
30 | $obj
= new A;
|
31 | $str
= serialize($obj); |
32 | echo
$str."\n"; //O:1:"A":3:{s:1:"a";s:8:"a string";s:1:"b";i:123;s:1:"c";d:123.1200000000000045474735088646411895751953125;} |
33 | $obj2
= unserialize($str); //进行反序列化
|
34 | var_dump($obj2==
$obj); //bool(true) |
程序运行时, serialize() 检查类中是否有 __sleep() ,如果有,则该函数将在任何序列化之前运行. 该函数必须返回一个需要进行序列化保存的成员属性数组,并且只序列化该函数返回的这些成员属性. 该函数有两个作用: 第一. 在序列化之前,关闭对象可能具有的任何数据库连接等. 第二. 指定对象中需要被序列化的成员属性,如果某个属性比较大而不需要储存下来,可以不把它写进__sleep()要返回的数组中,这样该属性就不会被序列化
__sleep() 方法常被用于提交未提交的数据, 或者类似的操作.
与 __sleep() 方法相反的情况, unserialize() 函数会检测是否存在 __wakeup() 函数, 如果存在会先调用 __wakeup(), 预先准备对象数据. 在用 unserialize()时需要注意的一个问题: 在一个PHP页面中要 unserialize() 一个对象,需要该页面包含该对象的类的定义.也就是,如果序列化了 page1.php 中类 A 的对象 $a, 要在 page2.php 中将其反序列化重建类 A 的对象 $a, 则 page2.php 中必须要出现类 A 的定义. 这可以这样实现,将类 A 的定义放在一个包含文件中,并在 page1.php 和 page2.php 都包含此文件. 所以强烈建议在所有的页面中都包括这些注册的对象的类的定义, 即使并不是在所有的页面中都用到了这些类. 如果没有这样做, 一个对象被反序列化了但却没有其类的定义,它将失去与之关联的类并成为 stdClass 的一个对象而完全没有任何可用的函数。
01 | //classa.inc: |
02 | class
A |
03 | { |
04 | var$one
= 1; |
05 | |
06 | functionshow_one()
|
07 | {
|
08 | echo$this->one;
|
09 | }
|
10 | } |
11 | |
12 | //page1.php: |
13 | include("classa.inc"); |
14 | |
15 | $a
= new A; |
16 | $s
= serialize($a); |
17 | $fp
= fopen("store","w");
// 将 $s 存放在某处使 page2.php 能够找到 |
18 | fputs($fp,$s);
|
19 | fclose($fp); |
20 | |
21 | //page2.php: |
22 | include("classa.inc"); // 为了正常解序列化需要这一行
|
23 | |
24 | $s
= implode("", @file("store")); |
25 | $a
= unserialize($s); |
26 | |
27 | $a->show_one();// 现在可以用 $a 对象的 show_one() 函数了 |
__wakeup() 方法经常用在反序列化操作中, 例如重新建立数据库连接,或其他的初始化工作.
例子:
01 | class
Connection { |
02 | protected$link;
|
03 | private$server,
$username,$password,
$db; |
04 | |
05 | publicfunction
__construct($server,$username,
$password,
$db) |
06 | {
|
07 | $this->server =$server;
|
08 | $this->username =$username;
|
09 | $this->password =$password;
|
10 | $this->db =$db;
|
11 | $this->connect(); |
12 | }
|
13 | |
14 | privatefunction
connect() |
15 | {
|
16 | $this->link = mysql_connect($this->server,$this->username,$this->password); |
17 | mysql_select_db($this->db,$this->link);
|
18 | }
|
19 | |
20 | publicfunction
__sleep() |
21 | {
|
22 | returnarray('server','username',
'password',
'db'); |
23 | }
|
24 | |
25 | publicfunction
__wakeup() |
26 | {
|
27 | $this->connect(); |
28 | }
|
29 | } |
本文详细介绍了PHP中序列化的基本概念,包括整型、浮点型、字符串、布尔型、数组变量和对象序列化的具体操作。同时,阐述了序列化在session中的应用以及如何通过__sleep()和__wakeup()函数优化对象序列化过程,确保资源的有效释放和对象状态的正确保存。
1108

被折叠的 条评论
为什么被折叠?



