/
034_3.php
141 lines (128 loc) · 3.49 KB
/
034_3.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<?php
declare(strict_types=1);
error_reporting(-1);
/* __clone() */
class Clone1
{
public function __construct(
private int $num,
private string $str,
){}
public function __clone(): void
{
$this->num += 456;
$this->str .= ' add';
}
}
$object = new Clone1(123, 'str');
$object2 = clone $object;
var_dump($object, $object2);
// 「外からcloneさせたくない」といった意図で、アクセス権を public 以外にする事もできます。
class Clone2
{
public function __construct(
private int $num,
private string $str,
){}
private function __clone(): void
{
}
public function copy(): static
{
return clone $this;
}
}
$object = new Clone2(123, 'str');
// $object2 = clone $object; // Fatal error: Uncaught Error: Call to private Clone2::__clone() from global scope
$object2 = $object->copy();
var_dump($object, $object2);
/* __sleep() と __wakeup() 、__serialize() と __unserialize() */
class SleepWakeup
{
public function __construct(
private int $num,
private float $f,
private bool $b,
){}
//
public function __sleep(): array
{
return ['num', 'b'];
}
public function __wakeup(): void
{
$this->f = $this->num / 10;
}
}
$object = new SleepWakeup(123, 3.14, true);
$object_string = serialize($object);
$object2 = unserialize($object_string);
var_dump($object, $object_string, $object2);
class SerializeUnserialize
{
public function __construct(
private int $num,
private float $f,
private bool $b,
){}
//
public function __serialize(): array
{
return [
'num' => $this->num,
'b' => $this->b,
];
}
public function __unserialize(array $data): void
{
$this->num = $data['num'];
$this->b = $data['b'];
$this->f = $this->num / 10;
}
}
$object = new SerializeUnserialize(123, 3.14, true);
$object_string = serialize($object);
$object2 = unserialize($object_string);
var_dump($object, $object_string, $object2);
// `__sleep()` と `__serialize()` は基本的に「どちらか片方のみが定義されている」事が期待されています。両方とも定義されている場合、`__serialize()` のみが起動します。
// `__wakeup()` と `__unserialize()` は基本的に「どちらか片方のみが定義されている」事が期待されています。両方とも定義されている場合、`__unserialize()` のみが起動します。
class SleepWakeupSerializeUnserialize
{
public function __construct(
private int $num,
private float $f,
private bool $b,
){}
//
public function __sleep(): array
{
echo "run __sleep() \n";
return ['num', 'b'];
}
public function __wakeup(): void
{
echo "run __wakeup() \n";
$this->f = $this->num / 10;
}
//
public function __serialize(): array
{
echo "run __serialize() \n";
return [
'num' => $this->num,
'b' => $this->b,
];
}
public function __unserialize(array $data): void
{
echo "run __unserialize() \n";
$this->num = $data['num'];
$this->b = $data['b'];
$this->f = $this->num / 10;
}
}
echo "serialize start \n";
$object = new SleepWakeupSerializeUnserialize(123, 3.14, true);
$object_string = serialize($object);
$object2 = unserialize($object_string);
echo "end \n";