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 ed695a6

Browse filesBrowse files
[DependencyInjection] Leverage native lazy objects for lazy services
1 parent c95120d commit ed695a6
Copy full SHA for ed695a6

27 files changed

+1212
-187
lines changed

‎src/Symfony/Bridge/Doctrine/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/CHANGELOG.md
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Reset the manager registry using native lazy objects when applicable
8+
49
7.2
510
---
611

‎src/Symfony/Bridge/Doctrine/ManagerRegistry.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/ManagerRegistry.php
+53-24Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -45,31 +45,60 @@ protected function resetService($name): void
4545

4646
return;
4747
}
48-
if (!$manager instanceof LazyLoadingInterface) {
49-
throw new \LogicException(\sprintf('Resetting a non-lazy manager service is not supported. Declare the "%s" service as lazy.', $name));
48+
if (\PHP_VERSION_ID < 80400) {
49+
if (!$manager instanceof LazyLoadingInterface) {
50+
throw new \LogicException(\sprintf('Resetting a non-lazy manager service is not supported. Declare the "%s" service as lazy.', $name));
51+
}
52+
trigger_deprecation('symfony/doctrine-bridge', '7.3', 'Support for proxy-manager is deprecated.');
53+
54+
if ($manager instanceof GhostObjectInterface) {
55+
throw new \LogicException('Resetting a lazy-ghost-object manager service is not supported.');
56+
}
57+
$manager->setProxyInitializer(\Closure::bind(
58+
function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) {
59+
$name = $this->aliases[$name] ?? $name;
60+
$wrappedInstance = match (true) {
61+
isset($this->fileMap[$name]) => $this->load($this->fileMap[$name], false),
62+
(new \ReflectionMethod($this, $method = $this->methodMap[$name]))->isStatic() => $this->{$method}($this, false),
63+
default => $this->{$method}(false),
64+
};
65+
$manager->setProxyInitializer(null);
66+
67+
return true;
68+
},
69+
$this->container,
70+
Container::class
71+
));
72+
73+
return;
5074
}
51-
if ($manager instanceof GhostObjectInterface) {
52-
throw new \LogicException('Resetting a lazy-ghost-object manager service is not supported.');
75+
76+
$r = new \ReflectionClass($manager);
77+
78+
if ($r->isUninitializedLazyObject($manager)) {
79+
return;
80+
}
81+
82+
try {
83+
$r->resetAsLazyProxy($manager, \Closure::bind(
84+
function () use ($name) {
85+
$name = $this->aliases[$name] ?? $name;
86+
87+
return match (true) {
88+
isset($this->fileMap[$name]) => $this->load($this->fileMap[$name], false),
89+
(new \ReflectionMethod($this, $method = $this->methodMap[$name]))->isStatic() => $this->{$method}($this, false),
90+
default => $this->{$method}(false),
91+
};
92+
},
93+
$this->container,
94+
Container::class
95+
));
96+
} catch (\Error $e) {
97+
if (__FILE__ !== $e->getFile()) {
98+
throw $e;
99+
}
100+
101+
throw new \LogicException(\sprintf('Resetting a non-lazy manager service is not supported. Declare the "%s" service as lazy.', $name), 0, $e);
53102
}
54-
$manager->setProxyInitializer(\Closure::bind(
55-
function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) {
56-
if (isset($this->aliases[$name])) {
57-
$name = $this->aliases[$name];
58-
}
59-
if (isset($this->fileMap[$name])) {
60-
$wrappedInstance = $this->load($this->fileMap[$name], false);
61-
} elseif ((new \ReflectionMethod($this, $this->methodMap[$name]))->isStatic()) {
62-
$wrappedInstance = $this->{$this->methodMap[$name]}($this, false);
63-
} else {
64-
$wrappedInstance = $this->{$this->methodMap[$name]}(false);
65-
}
66-
67-
$manager->setProxyInitializer(null);
68-
69-
return true;
70-
},
71-
$this->container,
72-
Container::class
73-
));
74103
}
75104
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ CHANGELOG
99
* Don't skip classes with private constructor when autodiscovering
1010
* Add `Definition::addExcludeTag()` and `ContainerBuilder::findExcludedServiceIds()`
1111
for auto-configuration of classes excluded from the service container
12+
* Leverage native lazy objects when possible for lazy services
1213

1314
7.2
1415
---

‎src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/LazyServiceInstantiator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/LazyServiceInstantiator.php
+11-2Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,19 @@ public function instantiateProxy(ContainerInterface $container, Definition $defi
2929
throw new InvalidArgumentException(\sprintf('Cannot instantiate lazy proxy for service "%s".', $id));
3030
}
3131

32-
if (!class_exists($proxyClass = $dumper->getProxyClass($definition, $asGhostObject), false)) {
32+
if (\PHP_VERSION_ID >= 80400 && $asGhostObject) {
33+
return (new \ReflectionClass($definition->getClass()))->newLazyGhost(static function ($ghost) use ($realInstantiator) { $realInstantiator($ghost); });
34+
}
35+
36+
$class = null;
37+
if (!class_exists($proxyClass = $dumper->getProxyClass($definition, $asGhostObject, $class), false)) {
3338
eval($dumper->getProxyCode($definition, $id));
3439
}
3540

36-
return $asGhostObject ? $proxyClass::createLazyGhost($realInstantiator) : $proxyClass::createLazyProxy($realInstantiator);
41+
if ($definition->getClass() === $proxyClass) {
42+
return $class->newLazyProxy($realInstantiator);
43+
}
44+
45+
return \PHP_VERSION_ID < 80400 && $asGhostObject ? $proxyClass::createLazyGhost($realInstantiator) : $proxyClass::createLazyProxy($realInstantiator);
3746
}
3847
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/LazyServiceDumper.php
+57-4Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,21 @@ public function isProxyCandidate(Definition $definition, ?bool &$asGhostObject =
5656
}
5757
}
5858

59+
if (\PHP_VERSION_ID < 80400) {
60+
try {
61+
$asGhostObject = (bool) ProxyHelper::generateLazyGhost(new \ReflectionClass($class));
62+
} catch (LogicException) {
63+
}
64+
65+
return true;
66+
}
67+
5968
try {
60-
$asGhostObject = (bool) ProxyHelper::generateLazyGhost(new \ReflectionClass($class));
61-
} catch (LogicException) {
69+
$asGhostObject = (bool) (new \ReflectionClass($class))->newLazyGhost(static fn () => null);
70+
} catch (\Error $e) {
71+
if (__FILE__ !== $e->getFile()) {
72+
throw $e;
73+
}
6274
}
6375

6476
return true;
@@ -76,6 +88,16 @@ public function getProxyFactoryCode(Definition $definition, string $id, string $
7688
$proxyClass = $this->getProxyClass($definition, $asGhostObject);
7789

7890
if (!$asGhostObject) {
91+
if ($definition->getClass() === $proxyClass) {
92+
return <<<EOF
93+
if (true === \$lazyLoad) {
94+
$instantiation new \ReflectionClass('$proxyClass')->newLazyProxy(static fn () => $factoryCode);
95+
}
96+
97+
98+
EOF;
99+
}
100+
79101
return <<<EOF
80102
if (true === \$lazyLoad) {
81103
$instantiation \$container->createProxy('$proxyClass', static fn () => \\$proxyClass::createLazyProxy(static fn () => $factoryCode));
@@ -85,11 +107,23 @@ public function getProxyFactoryCode(Definition $definition, string $id, string $
85107
EOF;
86108
}
87109

88-
$factoryCode = \sprintf('static fn ($proxy) => %s', $factoryCode);
110+
if (\PHP_VERSION_ID < 80400) {
111+
$factoryCode = \sprintf('static fn ($proxy) => %s', $factoryCode);
112+
113+
return <<<EOF
114+
if (true === \$lazyLoad) {
115+
$instantiation \$container->createProxy('$proxyClass', static fn () => \\$proxyClass::createLazyGhost($factoryCode));
116+
}
117+
118+
119+
EOF;
120+
}
121+
122+
$factoryCode = \sprintf('static function ($proxy) use ($container) { %s; }', $factoryCode);
89123

90124
return <<<EOF
91125
if (true === \$lazyLoad) {
92-
$instantiation \$container->createProxy('$proxyClass', static fn () => \\$proxyClass::createLazyGhost($factoryCode));
126+
$instantiation new \ReflectionClass('$proxyClass')->newLazyGhost($factoryCode);
93127
}
94128
95129
@@ -104,12 +138,21 @@ public function getProxyCode(Definition $definition, ?string $id = null): string
104138
$proxyClass = $this->getProxyClass($definition, $asGhostObject, $class);
105139

106140
if ($asGhostObject) {
141+
if (\PHP_VERSION_ID >= 80400) {
142+
return '';
143+
}
144+
107145
try {
108146
return ($class?->isReadOnly() ? 'readonly ' : '').'class '.$proxyClass.ProxyHelper::generateLazyGhost($class);
109147
} catch (LogicException $e) {
110148
throw new InvalidArgumentException(\sprintf('Cannot generate lazy ghost for service "%s".', $id ?? $definition->getClass()), 0, $e);
111149
}
112150
}
151+
152+
if ($definition->getClass() === $proxyClass) {
153+
return '';
154+
}
155+
113156
$interfaces = [];
114157

115158
if ($definition->hasTag('proxy')) {
@@ -144,6 +187,16 @@ public function getProxyClass(Definition $definition, bool $asGhostObject, ?\Ref
144187
$class = 'object' !== $definition->getClass() ? $definition->getClass() : 'stdClass';
145188
$class = new \ReflectionClass($class);
146189

190+
if (\PHP_VERSION_ID >= 80400) {
191+
if ($asGhostObject) {
192+
return $class->name;
193+
}
194+
195+
if (!$definition->hasTag('proxy') && !$class->isInterface()) {
196+
return $class->name;
197+
}
198+
}
199+
147200
return preg_replace('/^.*\\\\/', '', $definition->getClass())
148201
.($asGhostObject ? 'Ghost' : 'Proxy')
149202
.ucfirst(substr(hash('xxh128', $this->salt.'+'.$class->name.'+'.serialize($definition->getTag('proxy'))), -7));

‎src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1919,8 +1919,12 @@ public function testLazyWither()
19191919
$container->compile();
19201920

19211921
$wither = $container->get('wither');
1922+
if (\PHP_VERSION_ID >= 80400) {
1923+
$this->assertTrue((new \ReflectionClass($wither))->isUninitializedLazyObject($wither));
1924+
} else {
1925+
$this->assertTrue($wither->resetLazyObject());
1926+
}
19221927
$this->assertInstanceOf(Foo::class, $wither->foo);
1923-
$this->assertTrue($wither->resetLazyObject());
19241928
$this->assertInstanceOf(Wither::class, $wither->withFoo1($wither->foo));
19251929
}
19261930

0 commit comments

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