Skip to content

Commit 256e765

Browse files
[DI] Allow dumping the container in one file instead of many files
1 parent 52e9fb9 commit 256e765

File tree

2 files changed

+65
-23
lines changed

2 files changed

+65
-23
lines changed

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
4.4.0
55
-----
66

7+
* added support for dumping the container in one file instead of many files
78
* deprecated support for short factories and short configurators in Yaml
89
* deprecated `tagged` in favor of `tagged_iterator`
910
* deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition`

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

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class PhpDumper extends Dumper
7272
private $namespace;
7373
private $asFiles;
7474
private $hotPathTag;
75+
private $inlineFactories;
7576
private $inlineRequires;
7677
private $inlinedRequires = [];
7778
private $circularReferences = [];
@@ -134,6 +135,7 @@ public function dump(array $options = [])
134135
'as_files' => false,
135136
'debug' => true,
136137
'hot_path_tag' => 'container.hot_path',
138+
'inline_factories_parameter' => 'container.dumper.inline_factories',
137139
'inline_class_loader_parameter' => 'container.dumper.inline_class_loader',
138140
'service_locator_tag' => 'container.service_locator',
139141
'build_time' => time(),
@@ -143,6 +145,7 @@ public function dump(array $options = [])
143145
$this->namespace = $options['namespace'];
144146
$this->asFiles = $options['as_files'];
145147
$this->hotPathTag = $options['hot_path_tag'];
148+
$this->inlineFactories = $this->asFiles && $options['inline_factories_parameter'] && $this->container->hasParameter($options['inline_factories_parameter']) && $this->container->getParameter($options['inline_factories_parameter']);
146149
$this->inlineRequires = $options['inline_class_loader_parameter'] && $this->container->hasParameter($options['inline_class_loader_parameter']) && $this->container->getParameter($options['inline_class_loader_parameter']);
147150
$this->serviceLocatorTag = $options['service_locator_tag'];
148151

@@ -215,6 +218,8 @@ public function dump(array $options = [])
215218
}
216219
}
217220

221+
$proxyClasses = $this->generateProxyClasses();
222+
218223
$code =
219224
$this->startClass($options['class'], $baseClass, $baseClassWithNamespace).
220225
$this->addServices($services).
@@ -258,13 +263,24 @@ public function dump(array $options = [])
258263
$files['removed-ids.php'] = $c .= "];\n";
259264
}
260265

261-
foreach ($this->generateServiceFiles($services) as $file => $c) {
262-
$files[$file] = $fileStart.$c;
266+
if (!$this->inlineFactories) {
267+
foreach ($this->generateServiceFiles($services) as $file => $c) {
268+
$files[$file] = $fileStart.$c;
269+
}
270+
foreach ($proxyClasses as $file => $c) {
271+
$files[$file] = "<?php\n".$c;
272+
}
263273
}
264-
foreach ($this->generateProxyClasses() as $file => $c) {
265-
$files[$file] = "<?php\n".$c;
274+
275+
$code .= $this->endClass();
276+
277+
if ($this->inlineFactories) {
278+
foreach ($proxyClasses as $c) {
279+
$code .= $c;
280+
}
266281
}
267-
$files[$options['class'].'.php'] = $code.$this->endClass();
282+
283+
$files[$options['class'].'.php'] = $code;
268284
$hash = ucfirst(strtr(ContainerBuilder::hash($files), '._', 'xx'));
269285
$code = [];
270286

@@ -303,7 +319,7 @@ public function dump(array $options = [])
303319
EOF;
304320
} else {
305321
$code .= $this->endClass();
306-
foreach ($this->generateProxyClasses() as $c) {
322+
foreach ($proxyClasses as $c) {
307323
$code .= $c;
308324
}
309325
}
@@ -422,8 +438,9 @@ private function collectLineage($class, array &$lineage)
422438
$lineage[$class] = substr($exportedFile, 1, -1);
423439
}
424440

425-
private function generateProxyClasses()
441+
private function generateProxyClasses(): array
426442
{
443+
$proxyClasses = [];
427444
$alreadyGenerated = [];
428445
$definitions = $this->container->getDefinitions();
429446
$strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments');
@@ -442,19 +459,39 @@ private function generateProxyClasses()
442459
if ("\n" === $proxyCode = "\n".$proxyDumper->getProxyCode($definition)) {
443460
continue;
444461
}
462+
463+
if ($this->inlineRequires) {
464+
$lineage = [];
465+
$this->collectLineage($class, $lineage);
466+
467+
$code = '';
468+
foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) {
469+
if ($this->inlineFactories) {
470+
$this->inlinedRequires[$file] = true;
471+
}
472+
$file = preg_replace('#^\\$this->targetDirs\[(\d++)\]#', sprintf('\dirname(__DIR__, %d + $1)', $this->asFiles), $file);
473+
$code .= sprintf("include_once %s;\n", $file);
474+
}
475+
476+
$proxyCode = $code.$proxyCode;
477+
}
478+
445479
if ($strip) {
446480
$proxyCode = "<?php\n".$proxyCode;
447481
$proxyCode = substr(Kernel::stripComments($proxyCode), 5);
448482
}
449-
yield sprintf('%s.php', explode(' ', $proxyCode, 3)[1]) => $proxyCode;
483+
484+
$proxyClasses[sprintf('%s.php', explode(' ', $proxyCode, 3)[1])] = $proxyCode;
450485
}
486+
487+
return $proxyClasses;
451488
}
452489

453490
private function addServiceInclude(string $cId, Definition $definition): string
454491
{
455492
$code = '';
456493

457-
if ($this->inlineRequires && !$this->isHotPath($definition)) {
494+
if ($this->inlineRequires && (!$this->isHotPath($definition) || $this->getProxyDumper()->isProxyCandidate($definition))) {
458495
$lineage = [];
459496
foreach ($this->inlinedDefinitions as $def) {
460497
if (!$def->isDeprecated() && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) {
@@ -685,7 +722,7 @@ private function addService(string $id, Definition $definition): array
685722
$lazyInitialization = '';
686723
}
687724

688-
$asFile = $this->asFiles && !$this->isHotPath($definition);
725+
$asFile = $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition);
689726
$methodName = $this->generateMethodName($id);
690727
if ($asFile) {
691728
$file = $methodName.'.php';
@@ -711,17 +748,16 @@ protected function {$methodName}($lazyInitialization)
711748
$this->serviceCalls = [];
712749
$this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls);
713750

714-
$code .= $this->addServiceInclude($id, $definition);
751+
if ($definition->isDeprecated()) {
752+
$code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id)));
753+
}
715754

716755
if ($this->getProxyDumper()->isProxyCandidate($definition)) {
717756
$factoryCode = $asFile ? ($definition->isShared() ? "\$this->load('%s.php', false)" : '$this->factories[%2$s](false)') : '$this->%s(false)';
718757
$code .= $this->getProxyDumper()->getProxyFactoryCode($definition, $id, sprintf($factoryCode, $methodName, $this->doExport($id)));
719758
}
720759

721-
if ($definition->isDeprecated()) {
722-
$code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id)));
723-
}
724-
760+
$code .= $this->addServiceInclude($id, $definition);
725761
$code .= $this->addInlineService($id, $definition);
726762

727763
if ($asFile) {
@@ -1024,7 +1060,7 @@ public function __construct()
10241060

10251061
$code .= $this->addSyntheticIds();
10261062
$code .= $this->addMethodMap();
1027-
$code .= $this->asFiles ? $this->addFileMap() : '';
1063+
$code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : '';
10281064
$code .= $this->addAliases();
10291065
$code .= $this->addInlineRequires();
10301066
$code .= <<<EOF
@@ -1043,7 +1079,7 @@ public function isCompiled()
10431079
EOF;
10441080
$code .= $this->addRemovedIds();
10451081

1046-
if ($this->asFiles) {
1082+
if ($this->asFiles && !$this->inlineFactories) {
10471083
$code .= <<<EOF
10481084
10491085
protected function load(\$file, \$lazyLoad = true)
@@ -1059,10 +1095,10 @@ protected function load(\$file, \$lazyLoad = true)
10591095
if (!$proxyDumper->isProxyCandidate($definition)) {
10601096
continue;
10611097
}
1062-
if ($this->asFiles) {
1098+
if ($this->asFiles && !$this->inlineFactories) {
10631099
$proxyLoader = '$this->load("{$class}.php")';
1064-
} elseif ($this->namespace) {
1065-
$proxyLoader = 'class_alias("'.$this->namespace.'\\\\{$class}", $class, false)';
1100+
} elseif ($this->namespace || $this->inlineFactories) {
1101+
$proxyLoader = 'class_alias(__NAMESPACE__."\\\\$class", $class, false)';
10661102
} else {
10671103
$proxyLoader = '';
10681104
}
@@ -1140,7 +1176,7 @@ private function addMethodMap(): string
11401176
$definitions = $this->container->getDefinitions();
11411177
ksort($definitions);
11421178
foreach ($definitions as $id => $definition) {
1143-
if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || $this->isHotPath($definition))) {
1179+
if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || $this->inlineFactories || $this->isHotPath($definition))) {
11441180
$code .= ' '.$this->doExport($id).' => '.$this->doExport($this->generateMethodName($id)).",\n";
11451181
}
11461182
}
@@ -1237,6 +1273,11 @@ private function addInlineRequires(): string
12371273

12381274
foreach ($this->container->findTaggedServiceIds($this->hotPathTag) as $id => $tags) {
12391275
$definition = $this->container->getDefinition($id);
1276+
1277+
if ($this->getProxyDumper()->isProxyCandidate($definition)) {
1278+
continue;
1279+
}
1280+
12401281
$inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]);
12411282

12421283
foreach ($inlinedDefinitions as $def) {
@@ -1578,7 +1619,7 @@ private function dumpValue($value, bool $interpolate = true): string
15781619
continue;
15791620
}
15801621
$definition = $this->container->findDefinition($id = (string) $v);
1581-
$load = !($definition->hasErrors() && $e = $definition->getErrors()) ? $this->asFiles && !$this->isHotPath($definition) : reset($e);
1622+
$load = !($definition->hasErrors() && $e = $definition->getErrors()) ? $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition) : reset($e);
15821623
$serviceMap .= sprintf("\n %s => [%s, %s, %s, %s],",
15831624
$this->export($k),
15841625
$this->export($definition->isShared() ? ($definition->isPublic() ? 'services' : 'privates') : false),
@@ -1716,7 +1757,7 @@ private function getServiceCall(string $id, Reference $reference = null): string
17161757
$code = sprintf('$this->%s[%s] = %s', $definition->isPublic() ? 'services' : 'privates', $this->doExport($id), $code);
17171758
}
17181759
$code = "($code)";
1719-
} elseif ($this->asFiles && !$this->isHotPath($definition)) {
1760+
} elseif ($this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition)) {
17201761
$code = sprintf("\$this->load('%s.php')", $this->generateMethodName($id));
17211762
if (!$definition->isShared()) {
17221763
$factory = sprintf('$this->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id));

0 commit comments

Comments
 (0)