Skip to content

Commit a770a58

Browse files
committed
bug #44010 [DependencyInjection] fix auto-refresh when inline_factories is enabled (nicolas-grekas)
This PR was merged into the 5.4 branch. Discussion ---------- [DependencyInjection] fix auto-refresh when inline_factories is enabled | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #43956 | License | MIT | Doc PR | - This is more an improvement than a bugfix to me, thus the 5.4 target. When `inline_factories` is set, we also inline proxy classes in the dumped container. This breaks auto-refreshing the cache when a proxyfied class is removed (as described in the linked issue). This PR fixes the issue by dumping proxy classes in a new `proxy-classes.php` file. This file is loaded only after the cache has been checked, when the container is initialized. Commits ------- de495a562f [DependencyInjection] fix auto-refresh when inline_factories is enabled
2 parents 7521beb + 6878e08 commit a770a58

File tree

6 files changed

+41
-30
lines changed

6 files changed

+41
-30
lines changed

Dumper/PhpDumper.php

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ public function dump(array $options = [])
222222
}
223223

224224
$code =
225-
$this->startClass($options['class'], $baseClass).
225+
$this->startClass($options['class'], $baseClass, $this->inlineFactories && $proxyClasses).
226226
$this->addServices($services).
227227
$this->addDeprecatedAliases().
228228
$this->addDefaultParametersMethod()
@@ -286,14 +286,15 @@ class %s extends {$options['class']}
286286

287287
$code .= $this->endClass();
288288

289-
if ($this->inlineFactories) {
289+
if ($this->inlineFactories && $proxyClasses) {
290+
$files['proxy-classes.php'] = "<?php\n\n";
291+
290292
foreach ($proxyClasses as $c) {
291-
$code .= $c;
293+
$files['proxy-classes.php'] .= $c;
292294
}
293295
}
294296

295297
$files[$options['class'].'.php'] = $code;
296-
$preloadedFiles[$options['class'].'.php'] = $options['class'].'.php';
297298
$hash = ucfirst(strtr(ContainerBuilder::hash($files), '._', 'xx'));
298299
$code = [];
299300

@@ -313,7 +314,9 @@ class %s extends {$options['class']}
313314
$autoloadFile = trim($this->export($autoloadFile), '()\\');
314315

315316
$preloadedFiles = array_reverse($preloadedFiles);
316-
$preloadedFiles = implode("';\nrequire __DIR__.'/", $preloadedFiles);
317+
if ('' !== $preloadedFiles = implode("';\nrequire __DIR__.'/", $preloadedFiles)) {
318+
$preloadedFiles = "require __DIR__.'/$preloadedFiles';\n";
319+
}
317320

318321
$code[$options['class'].'.preload.php'] = <<<EOF
319322
<?php
@@ -328,8 +331,8 @@ class %s extends {$options['class']}
328331
}
329332
330333
require $autoloadFile;
331-
require __DIR__.'/$preloadedFiles';
332-
334+
(require __DIR__.'/Container{$hash}/{$options['class']}.php')->set(\\Container{$hash}\\{$options['class']}::class, null);
335+
$preloadedFiles
333336
\$classes = [];
334337
335338
EOF;
@@ -1179,7 +1182,7 @@ private function addNewInstance(Definition $definition, string $return = '', str
11791182
return $return.sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments)).$tail;
11801183
}
11811184

1182-
private function startClass(string $class, string $baseClass): string
1185+
private function startClass(string $class, string $baseClass, bool $hasProxyClasses): string
11831186
{
11841187
$namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
11851188

@@ -1239,7 +1242,7 @@ public function __construct()
12391242
$code .= $this->addMethodMap();
12401243
$code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : '';
12411244
$code .= $this->addAliases();
1242-
$code .= $this->addInlineRequires();
1245+
$code .= $this->addInlineRequires($hasProxyClasses);
12431246
$code .= <<<EOF
12441247
}
12451248
@@ -1451,15 +1454,12 @@ protected function {$methodNameAlias}()
14511454
return $code;
14521455
}
14531456

1454-
private function addInlineRequires(): string
1457+
private function addInlineRequires(bool $hasProxyClasses): string
14551458
{
1456-
if (!$this->hotPathTag || !$this->inlineRequires) {
1457-
return '';
1458-
}
1459-
14601459
$lineage = [];
1460+
$hotPathServices = $this->hotPathTag && $this->inlineRequires ? $this->container->findTaggedServiceIds($this->hotPathTag) : [];
14611461

1462-
foreach ($this->container->findTaggedServiceIds($this->hotPathTag) as $id => $tags) {
1462+
foreach ($hotPathServices as $id => $tags) {
14631463
$definition = $this->container->getDefinition($id);
14641464

14651465
if ($this->getProxyDumper()->isProxyCandidate($definition)) {
@@ -1484,6 +1484,10 @@ private function addInlineRequires(): string
14841484
}
14851485
}
14861486

1487+
if ($hasProxyClasses) {
1488+
$code .= "\n include __DIR__.'/proxy-classes.php';";
1489+
}
1490+
14871491
return $code ? sprintf("\n \$this->privates['service_container'] = function () {%s\n };\n", $code) : '';
14881492
}
14891493

Tests/Fixtures/php/services10_as_files.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) {
133133
}
134134

135135
require dirname(__DIR__, %d).'%svendor/autoload.php';
136-
require __DIR__.'/Container%s/ProjectServiceContainer.php';
136+
(require __DIR__.'/Container%s/ProjectServiceContainer.php')->set(\Container%s\ProjectServiceContainer::class, null);
137137
require __DIR__.'/Container%s/getClosureService.php';
138138

139139
$classes = [];

Tests/Fixtures/php/services9_as_files.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) {
907907
}
908908

909909
require dirname(__DIR__, %d).'%svendor/autoload.php';
910-
require __DIR__.'/Container%s/ProjectServiceContainer.php';
910+
(require __DIR__.'/Container%s/ProjectServiceContainer.php')->set(\Container%s\ProjectServiceContainer::class, null);
911911
require __DIR__.'/Container%s/getThrowingOneService.php';
912912
require __DIR__.'/Container%s/getTaggedIteratorService.php';
913913
require __DIR__.'/Container%s/getServiceFromStaticMethodService.php';

Tests/Fixtures/php/services9_inlined_factories.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) {
562562
}
563563

564564
require dirname(__DIR__, %d).'%svendor/autoload.php';
565-
require __DIR__.'/Container%s/ProjectServiceContainer.php';
565+
(require __DIR__.'/Container%s/ProjectServiceContainer.php')->set(\Container%s\ProjectServiceContainer::class, null);
566566

567567
$classes = [];
568568
$classes[] = 'Bar\FooClass';

Tests/Fixtures/php/services9_lazy_inlined_factories.txt

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@ return [
99
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
1010
];
1111

12+
[Container%s/proxy-classes.php] => <?php
13+
14+
namespace Container%s;
15+
16+
include_once $this->targetDir.''.'/Fixtures/includes/foo.php';
17+
18+
class FooClass_%s extends \Bar\FooClass implements \ProxyManager\Proxy\VirtualProxyInterface
19+
%A
20+
21+
if (!\class_exists('FooClass_%s', false)) {
22+
\class_alias(__NAMESPACE__.'\\FooClass_%s', 'FooClass_%s', false);
23+
}
24+
1225
[Container%s/ProjectServiceContainer.php] => <?php
1326

1427
namespace Container%s;
@@ -45,6 +58,10 @@ class ProjectServiceContainer extends Container
4558
];
4659

4760
$this->aliases = [];
61+
62+
$this->privates['service_container'] = function () {
63+
include __DIR__.'/proxy-classes.php';
64+
};
4865
}
4966

5067
public function compile(): void
@@ -156,16 +173,6 @@ class ProjectServiceContainer extends Container
156173
];
157174
}
158175
}
159-
include_once $this->targetDir.''.'/Fixtures/includes/foo.php';
160-
161-
class FooClass_%s extends \Bar\FooClass implements \ProxyManager\Proxy\VirtualProxyInterface
162-
{
163-
%A
164-
}
165-
166-
if (!\class_exists('FooClass_%s', false)) {
167-
\class_alias(__NAMESPACE__.'\\FooClass_%s', 'FooClass_%s', false);
168-
}
169176

170177
[ProjectServiceContainer.preload.php] => <?php
171178

@@ -179,7 +186,7 @@ if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) {
179186
}
180187

181188
require dirname(__DIR__, %d).'%svendor/autoload.php';
182-
require __DIR__.'/Container%s/ProjectServiceContainer.php';
189+
(require __DIR__.'/Container%s/ProjectServiceContainer.php')->set(\Container%s\ProjectServiceContainer::class, null);
183190

184191
$classes = [];
185192
$classes[] = 'Bar\FooClass';

Tests/Fixtures/php/services_non_shared_lazy_as_files.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) {
144144
}
145145

146146
require dirname(__DIR__, %d).'%svendor/autoload.php';
147-
require __DIR__.'/Container%s/ProjectServiceContainer.php';
147+
(require __DIR__.'/Container%s/ProjectServiceContainer.php')->set(\Container%s\ProjectServiceContainer::class, null);
148148
require __DIR__.'/Container%s/proxy.php';
149149
require __DIR__.'/Container%s/getNonSharedFooService.php';
150150

0 commit comments

Comments
 (0)