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 9ad3a37

Browse filesBrowse files
committed
[DependencyInjection] Fix fetching lazy non-shared services multiple times
1 parent 0be2622 commit 9ad3a37
Copy full SHA for 9ad3a37

File tree

6 files changed

+239
-5
lines changed
Filter options

6 files changed

+239
-5
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/LazyServiceDumper.php
+5-2Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,17 @@ public function getProxyFactoryCode(Definition $definition, string $id, string $
7070

7171
if ($definition->isShared()) {
7272
$instantiation .= sprintf(' $this->%s[%s] =', $definition->isPublic() && !$definition->isPrivate() ? 'services' : 'privates', var_export($id, true));
73+
$nonSharedCode = '';
74+
} else {
75+
$nonSharedCode = sprintf(' || %s === $lazyLoad', var_export($id, true));
7376
}
7477

7578
$asGhostObject = str_contains($factoryCode, '$proxy');
7679
$proxyClass = $this->getProxyClass($definition, $asGhostObject);
7780

7881
if (!$asGhostObject) {
7982
return <<<EOF
80-
if (true === \$lazyLoad) {
83+
if (true === \$lazyLoad$nonSharedCode) {
8184
$instantiation \$this->createProxy('$proxyClass', fn () => \\$proxyClass::createLazyProxy(fn () => $factoryCode));
8285
}
8386
@@ -92,7 +95,7 @@ public function getProxyFactoryCode(Definition $definition, string $id, string $
9295
}
9396

9497
return <<<EOF
95-
if (true === \$lazyLoad) {
98+
if (true === \$lazyLoad$nonSharedCode) {
9699
$instantiation \$this->createProxy('$proxyClass', fn () => \\$proxyClass::createLazyGhost($factoryCode));
97100
}
98101

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
+65-1Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,39 @@ public function testInlinedDefinitionReferencingServiceContainer()
692692
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services13.php', $dumper->dump(), '->dump() dumps inline definitions which reference service_container');
693693
}
694694

695+
public function testNonSharedLazy()
696+
{
697+
$container = new ContainerBuilder();
698+
699+
$container
700+
->register('foo', Foo::class)
701+
->setFile(realpath(self::$fixturesPath.'/includes/foo_lazy.php'))
702+
->setShared(false)
703+
->setLazy(true)
704+
->setPublic(true);
705+
706+
$container->compile();
707+
$dumper = new PhpDumper($container);
708+
$dump = $dumper->dump([
709+
'class' => 'Symfony_DI_PhpDumper_Service_Non_Shared_Lazy',
710+
'file' => __DIR__,
711+
'inline_factories_parameter' => false,
712+
'inline_class_loader_parameter' => false,
713+
]);
714+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_non_shared_lazy_public.php', $dump);
715+
eval('?>'.$dump);
716+
717+
$container = new \Symfony_DI_PhpDumper_Service_Non_Shared_Lazy();
718+
719+
$foo1 = $container->get('foo');
720+
$this->assertTrue($foo1->resetLazyObject());
721+
722+
$foo2 = $container->get('foo');
723+
$this->assertTrue($foo2->resetLazyObject());
724+
725+
$this->assertNotSame($foo1, $foo2);
726+
}
727+
695728
/**
696729
* @testWith [false]
697730
* [true]
@@ -700,7 +733,7 @@ public function testNonSharedLazyDefinitionReferences(bool $asGhostObject)
700733
{
701734
$container = new ContainerBuilder();
702735
$container->register('foo', 'stdClass')->setShared(false)->setLazy(true);
703-
$container->register('bar', 'stdClass')->addArgument(new Reference('foo', ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, false))->setPublic(true);
736+
$container->register('bar', 'stdClass')->addArgument(new Reference('foo', ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE))->setPublic(true);
704737
$container->compile();
705738

706739
$dumper = new PhpDumper($container);
@@ -1459,6 +1492,37 @@ public function testLazyWither()
14591492
$this->assertTrue($wither->resetLazyObject());
14601493
}
14611494

1495+
public function testLazyWitherNonShared()
1496+
{
1497+
$container = new ContainerBuilder();
1498+
$container->register(Foo::class);
1499+
1500+
$container
1501+
->register('wither', Wither::class)
1502+
->setShared(false)
1503+
->setLazy(true)
1504+
->setPublic(true)
1505+
->setAutowired(true);
1506+
1507+
$container->compile();
1508+
$dumper = new PhpDumper($container);
1509+
$dump = $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Service_Wither_Lazy_Non_Shared']);
1510+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_wither_lazy_non_shared.php', $dump);
1511+
eval('?>'.$dump);
1512+
1513+
$container = new \Symfony_DI_PhpDumper_Service_Wither_Lazy_Non_Shared();
1514+
1515+
$wither1 = $container->get('wither');
1516+
$this->assertInstanceOf(Foo::class, $wither1->foo);
1517+
$this->assertTrue($wither1->resetLazyObject());
1518+
1519+
$wither2 = $container->get('wither');
1520+
$this->assertInstanceOf(Foo::class, $wither2->foo);
1521+
$this->assertTrue($wither2->resetLazyObject());
1522+
1523+
$this->assertNotSame($wither1, $wither2);
1524+
}
1525+
14621526
public function testWitherWithStaticReturnType()
14631527
{
14641528
$container = new ContainerBuilder();

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_non_shared_lazy_as_files.txt
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class getNonSharedFooService extends ProjectServiceContainer
2121
{
2222
$container->factories['non_shared_foo'] ??= fn () => self::do($container);
2323

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

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_non_shared_lazy_ghost.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ protected function getFooService($lazyLoad = true)
6767
{
6868
$this->factories['service_container']['foo'] ??= $this->getFooService(...);
6969

70-
if (true === $lazyLoad) {
70+
if (true === $lazyLoad || 'foo' === $lazyLoad) {
7171
return $this->createProxy('stdClassGhost5a8a5eb', fn () => \stdClassGhost5a8a5eb::createLazyGhost($this->getFooService(...)));
7272
}
7373

+79Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
use Symfony\Component\DependencyInjection\ContainerInterface;
5+
use Symfony\Component\DependencyInjection\Container;
6+
use Symfony\Component\DependencyInjection\Exception\LogicException;
7+
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
8+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
9+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
11+
12+
/**
13+
* @internal This class has been auto-generated by the Symfony Dependency Injection Component.
14+
*/
15+
class Symfony_DI_PhpDumper_Service_Non_Shared_Lazy extends Container
16+
{
17+
protected $parameters = [];
18+
19+
public function __construct()
20+
{
21+
$this->services = $this->privates = [];
22+
$this->methodMap = [
23+
'foo' => 'getFooService',
24+
];
25+
26+
$this->aliases = [];
27+
}
28+
29+
public function compile(): void
30+
{
31+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
32+
}
33+
34+
public function isCompiled(): bool
35+
{
36+
return true;
37+
}
38+
39+
protected function createProxy($class, \Closure $factory)
40+
{
41+
return $factory();
42+
}
43+
44+
/**
45+
* Gets the public 'foo' service.
46+
*
47+
* @return \Symfony\Component\DependencyInjection\Tests\Compiler\Foo
48+
*/
49+
protected function getFooService($lazyLoad = true)
50+
{
51+
$this->factories['foo'] ??= $this->getFooService(...);
52+
53+
if (true === $lazyLoad || 'foo' === $lazyLoad) {
54+
return $this->createProxy('FooGhostCf082ac', fn () => \FooGhostCf082ac::createLazyGhost($this->getFooService(...)));
55+
}
56+
57+
static $include = true;
58+
59+
if ($include) {
60+
include_once __DIR__.'/Fixtures/includes/foo_lazy.php';
61+
62+
$include = false;
63+
}
64+
65+
return $lazyLoad;
66+
}
67+
}
68+
69+
class FooGhostCf082ac extends \Symfony\Component\DependencyInjection\Tests\Compiler\Foo implements \Symfony\Component\VarExporter\LazyObjectInterface
70+
{
71+
use \Symfony\Component\VarExporter\LazyGhostTrait;
72+
73+
private const LAZY_OBJECT_PROPERTY_SCOPES = [];
74+
}
75+
76+
// Help opcache.preload discover always-needed symbols
77+
class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class);
78+
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
79+
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
+88Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
use Symfony\Component\DependencyInjection\ContainerInterface;
5+
use Symfony\Component\DependencyInjection\Container;
6+
use Symfony\Component\DependencyInjection\Exception\LogicException;
7+
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
8+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
9+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
11+
12+
/**
13+
* @internal This class has been auto-generated by the Symfony Dependency Injection Component.
14+
*/
15+
class Symfony_DI_PhpDumper_Service_Wither_Lazy_Non_Shared extends Container
16+
{
17+
protected $parameters = [];
18+
19+
public function __construct()
20+
{
21+
$this->services = $this->privates = [];
22+
$this->methodMap = [
23+
'wither' => 'getWitherService',
24+
];
25+
26+
$this->aliases = [];
27+
}
28+
29+
public function compile(): void
30+
{
31+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
32+
}
33+
34+
public function isCompiled(): bool
35+
{
36+
return true;
37+
}
38+
39+
public function getRemovedIds(): array
40+
{
41+
return [
42+
'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\Foo' => true,
43+
];
44+
}
45+
46+
protected function createProxy($class, \Closure $factory)
47+
{
48+
return $factory();
49+
}
50+
51+
/**
52+
* Gets the public 'wither' autowired service.
53+
*
54+
* @return \Symfony\Component\DependencyInjection\Tests\Compiler\Wither
55+
*/
56+
protected function getWitherService($lazyLoad = true)
57+
{
58+
$this->factories['wither'] ??= $this->getWitherService(...);
59+
60+
if (true === $lazyLoad || 'wither' === $lazyLoad) {
61+
return $this->createProxy('WitherProxy8cb632f', fn () => \WitherProxy8cb632f::createLazyProxy(fn () => $this->getWitherService(false)));
62+
}
63+
64+
$instance = new \Symfony\Component\DependencyInjection\Tests\Compiler\Wither();
65+
66+
$a = ($this->privates['Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\Foo'] ??= new \Symfony\Component\DependencyInjection\Tests\Compiler\Foo());
67+
68+
$instance = $instance->withFoo1($a);
69+
$instance = $instance->withFoo2($a);
70+
$instance->setFoo($a);
71+
72+
return $instance;
73+
}
74+
}
75+
76+
class WitherProxy8cb632f extends \Symfony\Component\DependencyInjection\Tests\Compiler\Wither implements \Symfony\Component\VarExporter\LazyObjectInterface
77+
{
78+
use \Symfony\Component\VarExporter\LazyProxyTrait;
79+
80+
private const LAZY_OBJECT_PROPERTY_SCOPES = [
81+
'foo' => [parent::class, 'foo', null],
82+
];
83+
}
84+
85+
// Help opcache.preload discover always-needed symbols
86+
class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class);
87+
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
88+
class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class);

0 commit comments

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