Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit17e0838

Browse files
[VarExporter] Add trait to help implement lazy loading ghost objects
1 parentbbf25d6 commit17e0838

File tree

15 files changed

+1016
-21
lines changed

15 files changed

+1016
-21
lines changed

‎src/Symfony/Component/VarExporter/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
6.2
55
---
66

7+
* Add`LazyGhostObjectTrait`
78
* Add`Hydrator::hydrate()`
89
* Preserve PHP references also when using`Hydrator::hydrate()` or`Instantiator::instantiate()`
910
* Add support for hydrating from native (array) casts

‎src/Symfony/Component/VarExporter/Hydrator.php‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,13 @@ public static function hydrate(object $instance, array $properties = [], array $
6262

6363
foreach ($propertiesas$name => &$value) {
6464
[$scope,$name] =$propertyScopes[$name] ?? [$class,$name];
65-
$scopedProperties[$scope][$name] = &$value;
65+
$scopedProperties[$scope ??$propertyScopes[$name][0]][$name] = &$value;
6666
}
67-
unset($value);
6867
}
6968

70-
foreach ($scopedPropertiesas$class =>$properties) {
69+
foreach ($scopedPropertiesas$scope =>$properties) {
7170
if ($properties) {
72-
(InternalHydrator::$simpleHydrators[$class] ??= InternalHydrator::getSimpleHydrator($class))($properties,$instance);
71+
(InternalHydrator::$simpleHydrators[$scope] ??= InternalHydrator::getSimpleHydrator($scope))($properties,$instance);
7372
}
7473
}
7574

‎src/Symfony/Component/VarExporter/Instantiator.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,6 @@ public static function instantiate(string $class, array $properties = [], array
5454
$instance =unserialize('O:'.\strlen($class).':"'.$class.'":0:{}');
5555
}
5656

57-
return Hydrator::hydrate($instance,$properties,$scopedProperties);
57+
return$properties ||$scopedProperties ?Hydrator::hydrate($instance,$properties,$scopedProperties) :$instance;
5858
}
5959
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\VarExporter\Internal;
13+
14+
/**
15+
* @internal
16+
*/
17+
enum EmptyScope
18+
{
19+
}

‎src/Symfony/Component/VarExporter/Internal/Hydrator.php‎

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,28 +155,35 @@ public static function getHydrator($class)
155155

156156
publicstaticfunctiongetSimpleHydrator($class)
157157
{
158-
$baseHydrator =self::$simpleHydrators['stdClass'] ??=staticfunction ($properties,$object) {
158+
$baseHydrator =self::$simpleHydrators['stdClass'] ??= (function ($properties,$object) {
159+
$readonly = (array)$this;
160+
159161
foreach ($propertiesas$name => &$value) {
160-
$object->$name = &$value;
162+
$object->$name =$value;
163+
164+
if (!($readonly[$name] ??false)) {
165+
$object->$name = &$value;
166+
}
161167
}
162-
};
168+
})->bindTo(new \stdClass());
163169

164170
switch ($class) {
165171
case'stdClass':
166172
return$baseHydrator;
167173

168174
case'ErrorException':
169-
return$baseHydrator->bindTo(null,newclass()extends \ErrorException {
175+
return$baseHydrator->bindTo(new \stdClass(),newclass()extends \ErrorException {
170176
});
171177

172178
case'TypeError':
173-
return$baseHydrator->bindTo(null,newclass()extends \Error {
179+
return$baseHydrator->bindTo(new \stdClass(),newclass()extends \Error {
174180
});
175181

176182
case'SplObjectStorage':
177183
returnstaticfunction ($properties,$object) {
178184
foreach ($propertiesas$name => &$value) {
179185
if ("\0" !==$name) {
186+
$object->$name =$value;
180187
$object->$name = &$value;
181188
continue;
182189
}
@@ -202,14 +209,22 @@ public static function getSimpleHydrator($class)
202209
if ("\0" ===$name) {
203210
$constructor($object,$value);
204211
}else {
212+
$object->$name =$value;
205213
$object->$name = &$value;
206214
}
207215
}
208216
};
209217
}
210218

211219
if (!$classReflector->isInternal()) {
212-
return$baseHydrator->bindTo(null,$class);
220+
$readonly =new \stdClass();
221+
foreach ($classReflector->getProperties(\ReflectionProperty::IS_READONLY)as$propertyReflector) {
222+
if ($class ===$propertyReflector->class) {
223+
$readonly->{$propertyReflector->name} =true;
224+
}
225+
}
226+
227+
return$baseHydrator->bindTo($readonly,$class);
213228
}
214229

215230
if ($classReflector->name !==$class) {
@@ -232,6 +247,7 @@ public static function getSimpleHydrator($class)
232247
if ($setValue =$propertySetters[$name] ??null) {
233248
$setValue($object,$value);
234249
}else {
250+
$object->$name =$value;
235251
$object->$name = &$value;
236252
}
237253
}
@@ -255,7 +271,11 @@ public static function getPropertyScopes($class)
255271
$propertyScopes["\0$class\0$name"] =$propertyScopes[$name] = [$class,$name];
256272
continue;
257273
}
258-
$propertyScopes[$name] = [$flags & \ReflectionProperty::IS_READONLY ?$property->class :$class,$name];
274+
if ($flags & \ReflectionProperty::IS_READONLY) {
275+
$class =$property->class;
276+
$propertyScopes["\0$class\0$name"] = [null,$name];
277+
}
278+
$propertyScopes[$name] = [$class,$name];
259279

260280
if (\ReflectionProperty::IS_PROTECTED &$flags) {
261281
$propertyScopes["\0*\0$name"] =$propertyScopes[$name];
@@ -269,6 +289,7 @@ public static function getPropertyScopes($class)
269289
if (!$property->isStatic()) {
270290
$name =$property->name;
271291
$propertyScopes["\0$class\0$name"] = [$class,$name];
292+
$propertyScopes[$name] ??= [$class,$name];
272293
}
273294
}
274295
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\VarExporter\Internal;
13+
14+
useSymfony\Component\VarExporter\Hydrator;
15+
useSymfony\Component\VarExporter\Internal\HydratorasInternalHydrator;
16+
17+
/**
18+
* @internal
19+
*/
20+
class LazyGhostObjectRegistry
21+
{
22+
publicconstSTATUS_UNINITIALIZED =1;
23+
publicconstSTATUS_INITIALIZING =2;
24+
publicconstSTATUS_INITIALIZED =3;
25+
26+
/**
27+
* @var array<int, \Closure>
28+
*/
29+
publicstatic$initializers = [];
30+
31+
/**
32+
* @var array<int, array<string, mixed>>
33+
*/
34+
publicstatic$knownProperties = [];
35+
36+
/**
37+
* @var array<class-string, array{0: array<string, mixed>, 1: list<\Closure>}>
38+
*/
39+
publicstatic$propertiesDefaults = [];
40+
41+
/**
42+
* @var array<class-string, \ReflectionClass>
43+
*/
44+
publicstatic$classReflectors = [];
45+
46+
/**
47+
* @var array<class-string, list<\Closure>>
48+
*/
49+
publicstatic$classResetters = [];
50+
51+
/**
52+
* @var array<class-string, array<string, int>>
53+
*/
54+
publicstatic$parentMethods = [];
55+
56+
publicstaticfunctiongetParentMethods($class)
57+
{
58+
$parent =get_parent_class($class);
59+
60+
return [
61+
'__get' =>$parent &&method_exists($parent,'__get') ? ((new \ReflectionMethod($parent,'__get'))->returnsReference() ?2 :1) :0,
62+
'__set' =>$parent &&method_exists($parent,'__set') ?1 :0,
63+
'__isset' =>$parent &&method_exists($parent,'__isset') ?1 :0,
64+
'__unset' =>$parent &&method_exists($parent,'__unset') ?1 :0,
65+
'__clone' =>$parent &&method_exists($parent,'__clone') ?1 :0,
66+
'__serialize' =>$parent &&method_exists($parent,'__serialize') ?1 :0,
67+
'__sleep' =>$parent &&method_exists($parent,'__sleep') ?1 :0,
68+
'__destruct' =>$parent &&method_exists($parent,'__destruct') ?1 :0,
69+
];
70+
}
71+
72+
publicstaticfunctiongetClassResetters($class)
73+
{
74+
$classProperties = [];
75+
foreach (InternalHydrator::$propertyScopes[$class] ??= InternalHydrator::getPropertyScopes($class)as$key => [$scope,$name]) {
76+
if ('lazyGhostObjectState' !==$name &&null !==$scope) {
77+
$classProperties[$scope][$name] =$key;
78+
}
79+
}
80+
81+
$resetters = [];
82+
foreach ($classPropertiesas$scope =>$properties) {
83+
$resetters[] = \Closure::bind(staticfunction ($instance,$knownProperties)use ($properties) {
84+
foreach ($propertiesas$name =>$key) {
85+
if (!\array_key_exists($key,$knownProperties)) {
86+
unset($instance->$name);
87+
continue;
88+
}
89+
$value =$knownProperties[$key];
90+
91+
if (null !==$value &&$value !==$instance->$name ??=$value) {
92+
$instance->$name =$value;
93+
}
94+
}
95+
},null,$scope);
96+
}
97+
98+
$resetters[] =staticfunction ($instance,$knownProperties) {
99+
foreach ((array)$instanceas$name =>$value) {
100+
if ("\0" !== ($name[0] ??'') && !\array_key_exists($name,$knownProperties)) {
101+
unset($instance->$name);
102+
}
103+
}
104+
105+
foreach ($knownPropertiesas$name =>$value) {
106+
if (null !==$value &&"\0" !== ($name[0] ??'') &&$value !==$instance->$name ??=$value) {
107+
$instance->$name =$value;
108+
}
109+
}
110+
};
111+
112+
return$resetters;
113+
}
114+
115+
publicstaticfunctioninitialize($instance, &$state)
116+
{
117+
$id =$state & ~3;
118+
$state =$id |self::STATUS_INITIALIZING;
119+
120+
$propertiesDefaults =self::$propertiesDefaults[\get_class($instance)];
121+
122+
foreach (self::$knownProperties[$id] ?? []as$key =>$value) {
123+
if (null !==$value) {
124+
$propertiesDefaults[$key] =$value;
125+
}
126+
}
127+
128+
Hydrator::hydrate($instance,$propertiesDefaults);
129+
self::$initializers[$id]($instance);
130+
131+
$state =$id |self::STATUS_INITIALIZED;
132+
133+
returntrue;
134+
}
135+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\VarExporter;
13+
14+
interface LazyGhostObjectInterface
15+
{
16+
/**
17+
* @param \Closure(static):void $initializer
18+
* @param array<string, mixed> $knownProperties The values of the properties that are already known and won't trigger lazy-loading.
19+
* A null means to skip the corresponding property without changing its value.
20+
*/
21+
publicstaticfunctioncreateLazyGhostObject(\Closure$initializer,array$knownProperties = []):static;
22+
23+
/**
24+
* Forces initialization of a lazy ghost object.
25+
*
26+
* Returns true on success, false if the object was already initialized.
27+
*/
28+
publicfunctioninitializeLazyGhostObject():bool;
29+
30+
/**
31+
* Tells if the object is already initialized or not.
32+
*/
33+
publicfunctionisLazyGhostObjectInitialized():bool;
34+
35+
/**
36+
* @param array<string, mixed> $knownProperties The values of the properties that are already known and won't trigger lazy-loading.
37+
* A null means to skip the corresponding property without changing its value.
38+
*
39+
* @return bool Returns false when the object cannot be reset, ie when it's not a ghost object
40+
*/
41+
publicfunctionresetLazyGhostObject(array$knownProperties =null):bool;
42+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp