Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f5d0f60

Browse files
[DependencyInjection] Generate different classes for ghost objects and virtual proxies
1 parent 3c1afda commit f5d0f60

10 files changed

+83
-106
lines changed

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,10 +545,10 @@ private function generateProxyClasses(): array
545545
if (!$definition = $this->isProxyCandidate($definition, $asGhostObject, $id)) {
546546
continue;
547547
}
548-
if (isset($alreadyGenerated[$class = $definition->getClass()])) {
548+
if (isset($alreadyGenerated[$asGhostObject][$class = $definition->getClass()])) {
549549
continue;
550550
}
551-
$alreadyGenerated[$class] = true;
551+
$alreadyGenerated[$asGhostObject][$class] = true;
552552
// register class' reflector for resource tracking
553553
$this->container->getReflectionClass($class);
554554
if ("\n" === $proxyCode = "\n".$proxyDumper->getProxyCode($definition, $id)) {

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\DependencyInjection\ContainerInterface;
1515
use Symfony\Component\DependencyInjection\Definition;
16+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1617
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\LazyServiceDumper;
1718
use Symfony\Component\VarExporter\LazyGhostTrait;
1819

@@ -25,10 +26,14 @@ public function instantiateProxy(ContainerInterface $container, Definition $defi
2526
{
2627
$dumper = new LazyServiceDumper();
2728

28-
if (!class_exists($proxyClass = $dumper->getProxyClass($definition, $class), false)) {
29+
if (!$dumper->isProxyCandidate($definition, $asGhostObject, $id)) {
30+
throw new InvalidArgumentException(sprintf('Cannot instantiate lazy proxy for service "%s".', $id));
31+
}
32+
33+
if (!class_exists($proxyClass = $dumper->getProxyClass($definition, $asGhostObject, $class), false)) {
2934
eval($dumper->getProxyCode($definition, $id));
3035
}
3136

32-
return isset(class_uses($proxyClass)[LazyGhostTrait::class]) ? $proxyClass::createLazyGhost($realInstantiator) : $proxyClass::createLazyProxy($realInstantiator);
37+
return $asGhostObject ? $proxyClass::createLazyGhost($realInstantiator) : $proxyClass::createLazyProxy($realInstantiator);
3338
}
3439
}

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,10 @@ public function getProxyFactoryCode(Definition $definition, string $id, string $
7272
$instantiation .= sprintf(' $this->%s[%s] =', $definition->isPublic() && !$definition->isPrivate() ? 'services' : 'privates', var_export($id, true));
7373
}
7474

75-
$proxyClass = $this->getProxyClass($definition);
75+
$asGhostObject = str_contains($factoryCode, '$proxy');
76+
$proxyClass = $this->getProxyClass($definition, $asGhostObject);
7677

77-
if (!str_contains($factoryCode, '$proxy')) {
78+
if (!$asGhostObject) {
7879
return <<<EOF
7980
if (true === \$lazyLoad) {
8081
$instantiation \$this->createProxy('$proxyClass', fn () => \\$proxyClass::createLazyProxy(fn () => $factoryCode));
@@ -104,7 +105,7 @@ public function getProxyCode(Definition $definition, string $id = null): string
104105
if (!$this->isProxyCandidate($definition, $asGhostObject, $id)) {
105106
throw new InvalidArgumentException(sprintf('Cannot instantiate lazy proxy for service "%s".', $id ?? $definition->getClass()));
106107
}
107-
$proxyClass = $this->getProxyClass($definition, $class);
108+
$proxyClass = $this->getProxyClass($definition, $asGhostObject, $class);
108109

109110
if ($asGhostObject) {
110111
try {
@@ -142,10 +143,12 @@ public function getProxyCode(Definition $definition, string $id = null): string
142143
}
143144
}
144145

145-
public function getProxyClass(Definition $definition, \ReflectionClass &$class = null): string
146+
public function getProxyClass(Definition $definition, bool $asGhostObject, \ReflectionClass &$class = null): string
146147
{
147148
$class = new \ReflectionClass($definition->getClass());
148149

149-
return preg_replace('/^.*\\\\/', '', $class->name).'_'.substr(hash('sha256', $this->salt.'+'.$class->name), -7);
150+
return preg_replace('/^.*\\\\/', '', $class->name)
151+
.($asGhostObject ? 'Ghost' : 'Proxy')
152+
.ucfirst(substr(hash('sha256', $this->salt.'+'.$class->name), -7));
150153
}
151154
}

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

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -772,24 +772,18 @@ public function testCircularReferenceAllowanceForLazyServices()
772772
$dumper->dump();
773773
}
774774

775-
/**
776-
* @testWith [false]
777-
* [true]
778-
*/
779-
public function testDedupLazyProxy(bool $asGhostObject)
775+
public function testDedupLazyProxy()
780776
{
781777
$container = new ContainerBuilder();
782778
$container->register('foo', 'stdClass')->setLazy(true)->setPublic(true);
783779
$container->register('bar', 'stdClass')->setLazy(true)->setPublic(true);
780+
$container->register('baz', 'stdClass')->setLazy(true)->setPublic(true)->setFactory('foo_bar');
781+
$container->register('buz', 'stdClass')->setLazy(true)->setPublic(true)->setFactory('foo_bar');
784782
$container->compile();
785783

786784
$dumper = new PhpDumper($container);
787785

788-
if (!$asGhostObject) {
789-
$dumper->setProxyDumper(new \DummyProxyDumper());
790-
}
791-
792-
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_dedup_lazy'.($asGhostObject ? '_ghost' : '_proxy').'.php', $dumper->dump());
786+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_dedup_lazy.php', $dumper->dump());
793787
}
794788

795789
public function testLazyArgumentProvideGenerator()

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_lazy_inlined_factories.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ namespace Container%s;
66

77
include_once $this->targetDir.''.'/Fixtures/includes/foo.php';
88

9-
class FooClass_2b16075 extends \Bar\FooClass implements \Symfony\Component\VarExporter\LazyObjectInterface
9+
class FooClassGhost2b16075 extends \Bar\FooClass implements \Symfony\Component\VarExporter\LazyObjectInterface
1010
%A
1111

12-
if (!\class_exists('FooClass_%s', false)) {
13-
\class_alias(__NAMESPACE__.'\\FooClass_%s', 'FooClass_%s', false);
12+
if (!\class_exists('FooClassGhost2b16075', false)) {
13+
\class_alias(__NAMESPACE__.'\\FooClassGhost2b16075', 'FooClassGhost2b16075', false);
1414
}
1515

1616
[Container%s/ProjectServiceContainer.php] => <?php
@@ -78,7 +78,7 @@ class ProjectServiceContainer extends Container
7878
protected function getLazyFooService($lazyLoad = true)
7979
{
8080
if (true === $lazyLoad) {
81-
return $this->services['lazy_foo'] = $this->createProxy('FooClass_2b16075', fn () => \FooClass_2b16075::createLazyGhost($this->getLazyFooService(...)));
81+
return $this->services['lazy_foo'] = $this->createProxy('FooClassGhost2b16075', fn () => \FooClassGhost2b16075::createLazyGhost($this->getLazyFooService(...)));
8282
}
8383

8484
include_once $this->targetDir.''.'/Fixtures/includes/foo_lazy.php';

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dedup_lazy_ghost.php renamed to src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dedup_lazy.php

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public function __construct()
2121
$this->services = $this->privates = [];
2222
$this->methodMap = [
2323
'bar' => 'getBarService',
24+
'baz' => 'getBazService',
25+
'buz' => 'getBuzService',
2426
'foo' => 'getFooService',
2527
];
2628

@@ -50,12 +52,40 @@ protected function createProxy($class, \Closure $factory)
5052
protected function getBarService($lazyLoad = true)
5153
{
5254
if (true === $lazyLoad) {
53-
return $this->services['bar'] = $this->createProxy('stdClass_5a8a5eb', fn () => \stdClass_5a8a5eb::createLazyGhost($this->getBarService(...)));
55+
return $this->services['bar'] = $this->createProxy('stdClassGhost5a8a5eb', fn () => \stdClassGhost5a8a5eb::createLazyGhost($this->getBarService(...)));
5456
}
5557

5658
return $lazyLoad;
5759
}
5860

61+
/**
62+
* Gets the public 'baz' shared service.
63+
*
64+
* @return \stdClass
65+
*/
66+
protected function getBazService($lazyLoad = true)
67+
{
68+
if (true === $lazyLoad) {
69+
return $this->services['baz'] = $this->createProxy('stdClassProxy5a8a5eb', fn () => \stdClassProxy5a8a5eb::createLazyProxy(fn () => $this->getBazService(false)));
70+
}
71+
72+
return \foo_bar();
73+
}
74+
75+
/**
76+
* Gets the public 'buz' shared service.
77+
*
78+
* @return \stdClass
79+
*/
80+
protected function getBuzService($lazyLoad = true)
81+
{
82+
if (true === $lazyLoad) {
83+
return $this->services['buz'] = $this->createProxy('stdClassProxy5a8a5eb', fn () => \stdClassProxy5a8a5eb::createLazyProxy(fn () => $this->getBuzService(false)));
84+
}
85+
86+
return \foo_bar();
87+
}
88+
5989
/**
6090
* Gets the public 'foo' shared service.
6191
*
@@ -64,14 +94,14 @@ protected function getBarService($lazyLoad = true)
6494
protected function getFooService($lazyLoad = true)
6595
{
6696
if (true === $lazyLoad) {
67-
return $this->services['foo'] = $this->createProxy('stdClass_5a8a5eb', fn () => \stdClass_5a8a5eb::createLazyGhost($this->getFooService(...)));
97+
return $this->services['foo'] = $this->createProxy('stdClassGhost5a8a5eb', fn () => \stdClassGhost5a8a5eb::createLazyGhost($this->getFooService(...)));
6898
}
6999

70100
return $lazyLoad;
71101
}
72102
}
73103

74-
class stdClass_5a8a5eb extends \stdClass implements \Symfony\Component\VarExporter\LazyObjectInterface
104+
class stdClassGhost5a8a5eb extends \stdClass implements \Symfony\Component\VarExporter\LazyObjectInterface
75105
{
76106
use \Symfony\Component\VarExporter\LazyGhostTrait;
77107

@@ -82,3 +112,18 @@ class stdClass_5a8a5eb extends \stdClass implements \Symfony\Component\VarExport
82112
class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class);
83113
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
84114
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
115+
116+
class stdClassProxy5a8a5eb extends \stdClass implements \Symfony\Component\VarExporter\LazyObjectInterface
117+
{
118+
use \Symfony\Component\VarExporter\LazyProxyTrait;
119+
120+
private const LAZY_OBJECT_PROPERTY_SCOPES = [
121+
'lazyObjectReal' => [self::class, 'lazyObjectReal', null],
122+
"\0".self::class."\0lazyObjectReal" => [self::class, 'lazyObjectReal', null],
123+
];
124+
}
125+
126+
// Help opcache.preload discover always-needed symbols
127+
class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class);
128+
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
129+
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class);

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dedup_lazy_proxy.php

Lines changed: 0 additions & 70 deletions
This file was deleted.

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_non_shared_lazy_as_files.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class getNonSharedFooService extends ProjectServiceContainer
2222
$container->factories['non_shared_foo'] ??= fn () => self::do($container);
2323

2424
if (true === $lazyLoad) {
25-
return $container->createProxy('FooLazyClass_f814e3a', fn () => \FooLazyClass_f814e3a::createLazyGhost(fn ($proxy) => self::do($container, $proxy)));
25+
return $container->createProxy('FooLazyClassGhostF814e3a', fn () => \FooLazyClassGhostF814e3a::createLazyGhost(fn ($proxy) => self::do($container, $proxy)));
2626
}
2727

2828
static $include = true;
@@ -37,11 +37,11 @@ class getNonSharedFooService extends ProjectServiceContainer
3737
}
3838
}
3939

40-
[Container%s/FooLazyClass_f814e3a.php] => <?php
40+
[Container%s/FooLazyClassGhostF814e3a.php] => <?php
4141

4242
namespace Container%s;
4343

44-
class FooLazyClass_f814e3a extends \Bar\FooLazyClass implements \Symfony\Component\VarExporter\LazyObjectInterface
44+
class FooLazyClassGhostF814e3a extends \Bar\FooLazyClass implements \Symfony\Component\VarExporter\LazyObjectInterface
4545
{
4646
use \Symfony\Component\VarExporter\LazyGhostTrait;
4747

@@ -53,8 +53,8 @@ class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class);
5353
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
5454
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
5555

56-
if (!\class_exists('FooLazyClass_f814e3a', false)) {
57-
\class_alias(__NAMESPACE__.'\\FooLazyClass_f814e3a', 'FooLazyClass_f814e3a', false);
56+
if (!\class_exists('FooLazyClassGhostF814e3a', false)) {
57+
\class_alias(__NAMESPACE__.'\\FooLazyClassGhostF814e3a', 'FooLazyClassGhostF814e3a', false);
5858
}
5959

6060
[Container%s/ProjectServiceContainer.php] => <?php
@@ -141,7 +141,7 @@ if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) {
141141

142142
require dirname(__DIR__, %d).'%svendor/autoload.php';
143143
(require __DIR__.'/ProjectServiceContainer.php')->set(\Container%s\ProjectServiceContainer::class, null);
144-
require __DIR__.'/Container%s/FooLazyClass_f814e3a.php';
144+
require __DIR__.'/Container%s/FooLazyClassGhostF814e3a.php';
145145
require __DIR__.'/Container%s/getNonSharedFooService.php';
146146

147147
$classes = [];

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_non_shared_lazy_ghost.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,14 @@ protected function getFooService($lazyLoad = true)
6868
$this->factories['service_container']['foo'] ??= $this->getFooService(...);
6969

7070
if (true === $lazyLoad) {
71-
return $this->createProxy('stdClass_5a8a5eb', fn () => \stdClass_5a8a5eb::createLazyGhost($this->getFooService(...)));
71+
return $this->createProxy('stdClassGhost5a8a5eb', fn () => \stdClassGhost5a8a5eb::createLazyGhost($this->getFooService(...)));
7272
}
7373

7474
return $lazyLoad;
7575
}
7676
}
7777

78-
class stdClass_5a8a5eb extends \stdClass implements \Symfony\Component\VarExporter\LazyObjectInterface
78+
class stdClassGhost5a8a5eb extends \stdClass implements \Symfony\Component\VarExporter\LazyObjectInterface
7979
{
8080
use \Symfony\Component\VarExporter\LazyGhostTrait;
8181

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_wither_lazy.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ protected function createProxy($class, \Closure $factory)
5656
protected function getWitherService($lazyLoad = true)
5757
{
5858
if (true === $lazyLoad) {
59-
return $this->services['wither'] = $this->createProxy('Wither_94fa281', fn () => \Wither_94fa281::createLazyProxy(fn () => $this->getWitherService(false)));
59+
return $this->services['wither'] = $this->createProxy('WitherProxy94fa281', fn () => \WitherProxy94fa281::createLazyProxy(fn () => $this->getWitherService(false)));
6060
}
6161

6262
$instance = new \Symfony\Component\DependencyInjection\Tests\Compiler\Wither();
@@ -71,7 +71,7 @@ protected function getWitherService($lazyLoad = true)
7171
}
7272
}
7373

74-
class Wither_94fa281 extends \Symfony\Component\DependencyInjection\Tests\Compiler\Wither implements \Symfony\Component\VarExporter\LazyObjectInterface
74+
class WitherProxy94fa281 extends \Symfony\Component\DependencyInjection\Tests\Compiler\Wither implements \Symfony\Component\VarExporter\LazyObjectInterface
7575
{
7676
use \Symfony\Component\VarExporter\LazyProxyTrait;
7777

0 commit comments

Comments
 (0)