Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d373c11

Browse filesBrowse files
committed
Implement new custom object serialization mechanism
RFC: https://wiki.php.net/rfc/custom_object_serialization
1 parent e7e2056 commit d373c11
Copy full SHA for d373c11

File tree

Expand file treeCollapse file tree

8 files changed

+457
-41
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

8 files changed

+457
-41
lines changed
Open diff view settings
Collapse file

‎UPGRADING‎

Copy file name to clipboardExpand all lines: UPGRADING
+15Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ PHP 7.4 UPGRADE NOTES
107107
This will enforce that $user->id can only be assigned integer and
108108
$user->name can only be assigned strings. For more information see the
109109
RFC: https://wiki.php.net/rfc/typed_properties_v2
110+
110111
. Added support for coalesce assign (??=) operator. For example:
111112

112113
$array['key'] ??= computeDefault();
@@ -156,6 +157,20 @@ PHP 7.4 UPGRADE NOTES
156157
. strip_tags() now also accepts an array of allowed tags: Instead of
157158
strip_tags($str, '<a><p>') you can now write strip_tags($str, ['a', 'p']).
158159

160+
. A new mechanism for custom object serialization has been added, which
161+
uses two new magic methods:
162+
163+
// Returns array containing all the necessary state of the object.
164+
public function __serialize(): array;
165+
166+
// Restores the object state from the given data array.
167+
public function __unserialize(array $data): void;
168+
169+
The new serialization mechanism supersedes the Serializable interface,
170+
which will be deprecated in the future.
171+
172+
RFC: https://wiki.php.net/rfc/custom_object_serialization
173+
159174
========================================
160175
3. Changes in SAPI modules
161176
========================================
Collapse file
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
__serialize() mechanism (001): Basics
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public $prop;
8+
public $prop2;
9+
public function __serialize() {
10+
return ["value" => $this->prop, 42 => $this->prop2];
11+
}
12+
public function __unserialize(array $data) {
13+
$this->prop = $data["value"];
14+
$this->prop2 = $data[42];
15+
}
16+
}
17+
18+
$test = new Test;
19+
$test->prop = "foobar";
20+
$test->prop2 = "barfoo";
21+
var_dump($s = serialize($test));
22+
var_dump(unserialize($s));
23+
24+
?>
25+
--EXPECT--
26+
string(58) "O:4:"Test":2:{s:5:"value";s:6:"foobar";i:42;s:6:"barfoo";}"
27+
object(Test)#2 (2) {
28+
["prop"]=>
29+
string(6) "foobar"
30+
["prop2"]=>
31+
string(6) "barfoo"
32+
}
Collapse file
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
__serialize() mechanism (002): TypeError on invalid return type
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public function __serialize() {
8+
return $this;
9+
}
10+
}
11+
12+
try {
13+
serialize(new Test);
14+
} catch (TypeError $e) {
15+
echo $e->getMessage(), "\n";
16+
}
17+
18+
?>
19+
--EXPECT--
20+
__serialize() must return an array
Collapse file
+56Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
--TEST--
2+
__serialize() mechanism (003): Interoperability of different serialization mechanisms
3+
--FILE--
4+
<?php
5+
6+
class Test implements Serializable {
7+
public function __sleep() {
8+
echo "__sleep() called\n";
9+
}
10+
11+
public function __wakeup() {
12+
echo "__wakeup() called\n";
13+
}
14+
15+
public function __serialize() {
16+
echo "__serialize() called\n";
17+
return ["key" => "value"];
18+
}
19+
20+
public function __unserialize(array $data) {
21+
echo "__unserialize() called\n";
22+
var_dump($data);
23+
}
24+
25+
public function serialize() {
26+
echo "serialize() called\n";
27+
return "payload";
28+
}
29+
30+
public function unserialize($payload) {
31+
echo "unserialize() called\n";
32+
var_dump($payload);
33+
}
34+
}
35+
36+
$test = new Test;
37+
var_dump($s = serialize($test));
38+
var_dump(unserialize($s));
39+
40+
var_dump(unserialize('C:4:"Test":7:{payload}'));
41+
42+
?>
43+
--EXPECT--
44+
__serialize() called
45+
string(37) "O:4:"Test":1:{s:3:"key";s:5:"value";}"
46+
__unserialize() called
47+
array(1) {
48+
["key"]=>
49+
string(5) "value"
50+
}
51+
object(Test)#2 (0) {
52+
}
53+
unserialize() called
54+
string(7) "payload"
55+
object(Test)#2 (0) {
56+
}
Collapse file
+131Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
--TEST--
2+
__serialize() mechanism (004): Delayed __unserialize() calls
3+
--FILE--
4+
<?php
5+
6+
class Wakeup {
7+
public $data;
8+
public function __construct(array $data) {
9+
$this->data = $data;
10+
}
11+
public function __wakeup() {
12+
echo "__wakeup() called\n";
13+
var_dump($this->data);
14+
$this->woken_up = true;
15+
}
16+
}
17+
18+
class Unserialize {
19+
public $data;
20+
public function __construct(array $data) {
21+
$this->data = $data;
22+
}
23+
public function __serialize() {
24+
return $this->data;
25+
}
26+
public function __unserialize(array $data) {
27+
$this->data = $data;
28+
echo "__unserialize() called\n";
29+
var_dump($this->data);
30+
$this->unserialized = true;
31+
}
32+
}
33+
34+
$obj = new Wakeup([new Unserialize([new Wakeup([new Unserialize([])])])]);
35+
var_dump($s = serialize($obj));
36+
var_dump(unserialize($s));
37+
38+
?>
39+
--EXPECT--
40+
string(126) "O:6:"Wakeup":1:{s:4:"data";a:1:{i:0;O:11:"Unserialize":1:{i:0;O:6:"Wakeup":1:{s:4:"data";a:1:{i:0;O:11:"Unserialize":0:{}}}}}}"
41+
__unserialize() called
42+
array(0) {
43+
}
44+
__wakeup() called
45+
array(1) {
46+
[0]=>
47+
object(Unserialize)#8 (2) {
48+
["data"]=>
49+
array(0) {
50+
}
51+
["unserialized"]=>
52+
bool(true)
53+
}
54+
}
55+
__unserialize() called
56+
array(1) {
57+
[0]=>
58+
object(Wakeup)#7 (2) {
59+
["data"]=>
60+
array(1) {
61+
[0]=>
62+
object(Unserialize)#8 (2) {
63+
["data"]=>
64+
array(0) {
65+
}
66+
["unserialized"]=>
67+
bool(true)
68+
}
69+
}
70+
["woken_up"]=>
71+
bool(true)
72+
}
73+
}
74+
__wakeup() called
75+
array(1) {
76+
[0]=>
77+
object(Unserialize)#6 (2) {
78+
["data"]=>
79+
array(1) {
80+
[0]=>
81+
object(Wakeup)#7 (2) {
82+
["data"]=>
83+
array(1) {
84+
[0]=>
85+
object(Unserialize)#8 (2) {
86+
["data"]=>
87+
array(0) {
88+
}
89+
["unserialized"]=>
90+
bool(true)
91+
}
92+
}
93+
["woken_up"]=>
94+
bool(true)
95+
}
96+
}
97+
["unserialized"]=>
98+
bool(true)
99+
}
100+
}
101+
object(Wakeup)#5 (2) {
102+
["data"]=>
103+
array(1) {
104+
[0]=>
105+
object(Unserialize)#6 (2) {
106+
["data"]=>
107+
array(1) {
108+
[0]=>
109+
object(Wakeup)#7 (2) {
110+
["data"]=>
111+
array(1) {
112+
[0]=>
113+
object(Unserialize)#8 (2) {
114+
["data"]=>
115+
array(0) {
116+
}
117+
["unserialized"]=>
118+
bool(true)
119+
}
120+
}
121+
["woken_up"]=>
122+
bool(true)
123+
}
124+
}
125+
["unserialized"]=>
126+
bool(true)
127+
}
128+
}
129+
["woken_up"]=>
130+
bool(true)
131+
}
Collapse file
+56Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
--TEST--
2+
__serialize() mechanism (005): parent::__unserialize() is safe
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
private $data;
8+
public function __construct(array $data) {
9+
$this->data = $data;
10+
}
11+
public function __serialize() {
12+
return $this->data;
13+
}
14+
public function __unserialize(array $data) {
15+
$this->data = $data;
16+
}
17+
}
18+
19+
class B extends A {
20+
private $data2;
21+
public function __construct(array $data, array $data2) {
22+
parent::__construct($data);
23+
$this->data2 = $data2;
24+
}
25+
public function __serialize() {
26+
return [$this->data2, parent::__serialize()];
27+
}
28+
public function __unserialize(array $payload) {
29+
[$data2, $data] = $payload;
30+
parent::__unserialize($data);
31+
$this->data2 = $data2;
32+
}
33+
}
34+
35+
$common = new stdClass;
36+
$obj = new B([$common], [$common]);
37+
var_dump($s = serialize($obj));
38+
var_dump(unserialize($s));
39+
40+
?>
41+
--EXPECT--
42+
string(63) "O:1:"B":2:{i:0;a:1:{i:0;O:8:"stdClass":0:{}}i:1;a:1:{i:0;r:3;}}"
43+
object(B)#3 (2) {
44+
["data2":"B":private]=>
45+
array(1) {
46+
[0]=>
47+
object(stdClass)#4 (0) {
48+
}
49+
}
50+
["data":"A":private]=>
51+
array(1) {
52+
[0]=>
53+
object(stdClass)#4 (0) {
54+
}
55+
}
56+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.