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

Commite382b2f

Browse files
[VarExporter] Leverage native lazy objects
1 parent18a5c70 commite382b2f

File tree

31 files changed

+972
-226
lines changed

31 files changed

+972
-226
lines changed

‎UPGRADE-7.3.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,10 @@ VarDumper
196196

197197
* Deprecate`ResourceCaster::castCurl()`,`ResourceCaster::castGd()` and`ResourceCaster::castOpensslX509()`
198198
* Mark all casters as`@internal`
199+
200+
VarExporter
201+
-----------
202+
203+
* Deprecate using`ProxyHelper::generateLazyProxy()` when native lazy proxies can be used - the method should be used to generate abstraction-based lazy decorators only
204+
* Deprecate`LazyGhostTrait` and`LazyProxyTrait`, use native lazy objects instead
205+
* Deprecate`ProxyHelper::generateLazyGhost()`, use native lazy objects instead

‎src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/LazyServiceDumper.php

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,18 +187,28 @@ public function getProxyClass(Definition $definition, bool $asGhostObject, ?\Ref
187187
$class ='object' !==$definition->getClass() ?$definition->getClass() :'stdClass';
188188
$class =new \ReflectionClass($class);
189189

190-
if (\PHP_VERSION_ID >=80400) {
191-
if ($asGhostObject) {
192-
return$class->name;
193-
}
190+
if (\PHP_VERSION_ID <80400) {
191+
returnpreg_replace('/^.*\\\\/','',$definition->getClass())
192+
.($asGhostObject ?'Ghost' :'Proxy')
193+
.ucfirst(substr(hash('xxh128',$this->salt.'+'.$class->name.'+'.serialize($definition->getTag('proxy'))), -7));
194+
}
195+
196+
if ($asGhostObject) {
197+
return$class->name;
198+
}
199+
200+
if (!$definition->hasTag('proxy') && !$class->isInterface()) {
201+
$parent =$class;
202+
do {
203+
$extendsInternalClass =$parent->isInternal();
204+
}while (!$extendsInternalClass &&$parent =$parent->getParentClass());
194205

195-
if (!$definition->hasTag('proxy') && !$class->isInterface()) {
206+
if (!$extendsInternalClass) {
196207
return$class->name;
197208
}
198209
}
199210

200-
returnpreg_replace('/^.*\\\\/','',$definition->getClass())
201-
.($asGhostObject ?'Ghost' :'Proxy')
211+
returnpreg_replace('/^.*\\\\/','',$definition->getClass()).'Proxy'
202212
.ucfirst(substr(hash('xxh128',$this->salt.'+'.$class->name.'+'.serialize($definition->getTag('proxy'))), -7));
203213
}
204214
}

‎src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2036,7 +2036,11 @@ public function testLazyAutowireAttributeWithIntersection()
20362036

20372037
$dumper =newPhpDumper($container);
20382038

2039-
$this->assertStringEqualsFile(self::$fixturesPath.'/php/lazy_autowire_attribute_with_intersection.php',$dumper->dump());
2039+
if (\PHP_VERSION_ID >=80400) {
2040+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/lazy_autowire_attribute_with_intersection.php',$dumper->dump());
2041+
}else {
2042+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/legacy_lazy_autowire_attribute_with_intersection.php',$dumper->dump());
2043+
}
20402044
}
20412045

20422046
publicfunctiontestCallableAdapterConsumer()

‎src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_autowire_attribute_with_intersection.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,16 @@ protected static function get_Lazy_Foo_QFdMZVKService($container, $lazyLoad = tr
7474

7575
class objectProxy1fd6daaimplements \Symfony\Component\DependencyInjection\Tests\Compiler\AInterface, \Symfony\Component\DependencyInjection\Tests\Compiler\IInterface, \Symfony\Component\VarExporter\LazyObjectInterface
7676
{
77-
use \Symfony\Component\VarExporter\LazyProxyTrait;
77+
use \Symfony\Component\VarExporter\Internal\LazyDecoratorTrait;
7878

7979
privateconstLAZY_OBJECT_PROPERTY_SCOPES = [];
8080

8181
publicfunctioninitializeLazyObject():\Symfony\Component\DependencyInjection\Tests\Compiler\AInterface&\Symfony\Component\DependencyInjection\Tests\Compiler\IInterface
8282
{
83-
if ($state =$this->lazyObjectState ??null) {
84-
return$state->realInstance ??= ($state->initializer)();
85-
}
86-
87-
return$this;
83+
return$this->lazyObjectState->realInstance;
8884
}
8985
}
9086

9187
// Help opcache.preload discover always-needed symbols
9288
class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class);
9389
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
94-
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
useSymfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
useSymfony\Component\DependencyInjection\ContainerInterface;
5+
useSymfony\Component\DependencyInjection\Container;
6+
useSymfony\Component\DependencyInjection\Exception\LogicException;
7+
useSymfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
8+
useSymfony\Component\DependencyInjection\Exception\RuntimeException;
9+
useSymfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
useSymfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
11+
12+
/**
13+
* @internal This class has been auto-generated by the Symfony Dependency Injection Component.
14+
*/
15+
class ProjectServiceContainerextends Container
16+
{
17+
protected$parameters = [];
18+
19+
publicfunction__construct()
20+
{
21+
$this->services =$this->privates = [];
22+
$this->methodMap = [
23+
'foo' =>'getFooService',
24+
];
25+
26+
$this->aliases = [];
27+
}
28+
29+
publicfunctioncompile():void
30+
{
31+
thrownewLogicException('You cannot compile a dumped container that was already compiled.');
32+
}
33+
34+
publicfunctionisCompiled():bool
35+
{
36+
returntrue;
37+
}
38+
39+
protectedfunctioncreateProxy($class,\Closure$factory)
40+
{
41+
return$factory();
42+
}
43+
44+
/**
45+
* Gets the public 'foo' shared autowired service.
46+
*
47+
* @return \Symfony\Component\DependencyInjection\Tests\Compiler\AAndIInterfaceConsumer
48+
*/
49+
protectedstaticfunctiongetFooService($container)
50+
{
51+
$a = ($container->privates['.lazy.foo.qFdMZVK'] ??self::get_Lazy_Foo_QFdMZVKService($container));
52+
53+
if (isset($container->services['foo'])) {
54+
return$container->services['foo'];
55+
}
56+
57+
return$container->services['foo'] =new \Symfony\Component\DependencyInjection\Tests\Compiler\AAndIInterfaceConsumer($a);
58+
}
59+
60+
/**
61+
* Gets the private '.lazy.foo.qFdMZVK' shared service.
62+
*
63+
* @return \object
64+
*/
65+
protectedstaticfunctionget_Lazy_Foo_QFdMZVKService($container,$lazyLoad =true)
66+
{
67+
if (true ===$lazyLoad) {
68+
return$container->privates['.lazy.foo.qFdMZVK'] =$container->createProxy('objectProxy1fd6daa',staticfn () => \objectProxy1fd6daa::createLazyProxy(staticfn () =>self::get_Lazy_Foo_QFdMZVKService($container,false)));
69+
}
70+
71+
return ($container->services['foo'] ??self::getFooService($container));
72+
}
73+
}
74+
75+
class objectProxy1fd6daaimplements \Symfony\Component\DependencyInjection\Tests\Compiler\AInterface, \Symfony\Component\DependencyInjection\Tests\Compiler\IInterface, \Symfony\Component\VarExporter\LazyObjectInterface
76+
{
77+
use \Symfony\Component\VarExporter\LazyProxyTrait;
78+
79+
privateconstLAZY_OBJECT_PROPERTY_SCOPES = [];
80+
81+
publicfunctioninitializeLazyObject():\Symfony\Component\DependencyInjection\Tests\Compiler\AInterface&\Symfony\Component\DependencyInjection\Tests\Compiler\IInterface
82+
{
83+
if ($state =$this->lazyObjectState ??null) {
84+
return$state->realInstance ??= ($state->initializer)();
85+
}
86+
87+
return$this;
88+
}
89+
}
90+
91+
// Help opcache.preload discover always-needed symbols
92+
class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class);
93+
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
94+
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class);

‎src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dedup_lazy.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ protected static function getBarService($container, $lazyLoad = true)
6666
protectedstaticfunctiongetBazService($container,$lazyLoad =true)
6767
{
6868
if (true ===$lazyLoad) {
69-
return$container->services['baz'] =new \ReflectionClass('stdClass')->newLazyProxy(staticfn () =>self::getBazService($container,false));
69+
return$container->services['baz'] =$container->createProxy('stdClassProxyAa01f12',staticfn () => \stdClassProxyAa01f12::createLazyProxy(staticfn () =>self::getBazService($container,false)));
7070
}
7171

7272
return\foo_bar();
@@ -80,7 +80,7 @@ protected static function getBazService($container, $lazyLoad = true)
8080
protectedstaticfunctiongetBuzService($container,$lazyLoad =true)
8181
{
8282
if (true ===$lazyLoad) {
83-
return$container->services['buz'] =new \ReflectionClass('stdClass')->newLazyProxy(staticfn () =>self::getBuzService($container,false));
83+
return$container->services['buz'] =$container->createProxy('stdClassProxyAa01f12',staticfn () => \stdClassProxyAa01f12::createLazyProxy(staticfn () =>self::getBuzService($container,false)));
8484
}
8585

8686
return\foo_bar();
@@ -100,3 +100,14 @@ protected static function getFooService($container, $lazyLoad = true)
100100
return$lazyLoad;
101101
}
102102
}
103+
104+
class stdClassProxyAa01f12extends \stdClassimplements \Symfony\Component\VarExporter\LazyObjectInterface
105+
{
106+
use \Symfony\Component\VarExporter\Internal\LazyDecoratorTrait;
107+
108+
privateconstLAZY_OBJECT_PROPERTY_SCOPES = [];
109+
}
110+
111+
// Help opcache.preload discover always-needed symbols
112+
class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class);
113+
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);

‎src/Symfony/Component/HttpKernel/Tests/Fixtures/LazyResettableService.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespaceSymfony\Component\HttpKernel\Tests\Fixtures;
1313

14-
class LazyResettableService
14+
class LazyResettableServiceextends \stdClass
1515
{
1616
publicstatic$counter =0;
1717

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Deprecate using`ProxyHelper::generateLazyProxy()` when native lazy proxies can be used - the method should be used to generate abstraction-based lazy decorators only
8+
* Deprecate`LazyGhostTrait` and`LazyProxyTrait`, use native lazy objects instead
9+
* Deprecate`ProxyHelper::generateLazyGhost()`, use native lazy objects instead
10+
411
7.2
512
---
613

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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\Serializer\Attribute\Ignore;
15+
useSymfony\Component\VarExporter\Internal\LazyObjectRegistryasRegistry;
16+
17+
/**
18+
* @internal
19+
*/
20+
trait LazyDecoratorTrait
21+
{
22+
#[Ignore]
23+
privatereadonlyLazyObjectState$lazyObjectState;
24+
25+
/**
26+
* Creates a lazy-loading decorator.
27+
*
28+
* @param \Closure():object $initializer Returns the proxied object
29+
* @param static|null $instance
30+
*/
31+
publicstaticfunctioncreateLazyProxy(\Closure$initializer, ?object$instance =null):static
32+
{
33+
$class =$instance ?$instance::class :static::class;
34+
35+
if (self::class ===$class &&\defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) {
36+
Hydrator::$propertyScopes[$class] ??=$class::LAZY_OBJECT_PROPERTY_SCOPES;
37+
}
38+
39+
$instance ??= (Registry::$classReflectors[$class] ??= ($r =new \ReflectionClass($class))->hasProperty('lazyObjectState')
40+
?$r
41+
:thrownew \LogicException('Cannot create a lazy proxy for a non-decorator object.')
42+
)->newInstanceWithoutConstructor();
43+
44+
$state =$instance->lazyObjectState ??=newLazyObjectState();
45+
$state->initializer =null;
46+
unset($state->realInstance);
47+
48+
foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class)as$reset) {
49+
$reset($instance, []);
50+
}
51+
$state->initializer =$initializer;
52+
53+
return$instance;
54+
}
55+
56+
publicfunction__construct(...$args)
57+
{
58+
self::createLazyProxy(staticfn () =>newparent(...$args),$this);
59+
}
60+
61+
publicfunction__destruct()
62+
{
63+
}
64+
65+
#[Ignore]
66+
publicfunctionisLazyObjectInitialized(bool$partial =false):bool
67+
{
68+
returnisset($this->lazyObjectState->realInstance);
69+
}
70+
71+
publicfunctioninitializeLazyObject():parent
72+
{
73+
return$this->lazyObjectState->realInstance;
74+
}
75+
76+
publicfunctionresetLazyObject():bool
77+
{
78+
if (!isset($this->lazyObjectState->initializer)) {
79+
returnfalse;
80+
}
81+
unset($this->lazyObjectState->realInstance);
82+
83+
returntrue;
84+
}
85+
86+
publicfunction &__get($name):mixed
87+
{
88+
$instance =$this->lazyObjectState->realInstance;
89+
$class =$this::class;
90+
91+
$propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class);
92+
$notByRef =0;
93+
94+
if ([, , ,$access] =$propertyScopes[$name] ??null) {
95+
$notByRef =$access & Hydrator::PROPERTY_NOT_BY_REF || ($access >>2) & \ReflectionProperty::IS_PRIVATE_SET;
96+
}
97+
98+
if ($notByRef ||2 !== ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['get'] ?:2)) {
99+
$value =$instance->$name;
100+
101+
return$value;
102+
}
103+
104+
try {
105+
return$instance->$name;
106+
}catch (\Error$e) {
107+
if (\Error::class !==$e::class || !str_starts_with($e->getMessage(),'Cannot access uninitialized non-nullable property')) {
108+
throw$e;
109+
}
110+
111+
try {
112+
$instance->$name = [];
113+
114+
return$instance->$name;
115+
}catch (\Error) {
116+
if (preg_match('/^Cannot access uninitialized non-nullable property ([^ ]++) by reference$/',$e->getMessage(),$matches)) {
117+
thrownew \Error('Typed property'.$matches[1].' must not be accessed before initialization',$e->getCode(),$e->getPrevious());
118+
}
119+
120+
throw$e;
121+
}
122+
}
123+
}
124+
125+
publicfunction__set($name,$value):void
126+
{
127+
$this->lazyObjectState->realInstance->$name =$value;
128+
}
129+
130+
publicfunction__isset($name):bool
131+
{
132+
returnisset($this->lazyObjectState->realInstance->$name);
133+
}
134+
135+
publicfunction__unset($name):void
136+
{
137+
if ($this->lazyObjectState->initializer) {
138+
unset($this->lazyObjectState->realInstance->$name);
139+
}
140+
}
141+
142+
publicfunction__serialize():array
143+
{
144+
return [$this->lazyObjectState->realInstance];
145+
}
146+
147+
publicfunction__unserialize($data):void
148+
{
149+
$this->lazyObjectState =newLazyObjectState();
150+
$this->lazyObjectState->realInstance =$data[0];
151+
}
152+
153+
publicfunction__clone():void
154+
{
155+
$this->lazyObjectState->realInstance;// initialize lazy object
156+
$this->lazyObjectState =clone$this->lazyObjectState;
157+
}
158+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp