diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index b4881b70d3..c5ada9ee20 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -43,6 +43,7 @@ class Container implements ResettableContainerInterface protected $services = array(); protected $fileMap = array(); protected $methodMap = array(); + protected $factories = array(); protected $aliases = array(); protected $loading = array(); protected $resolving = array(); @@ -227,6 +228,9 @@ class Container implements ResettableContainerInterface if ('service_container' === $id) { return $this; } + if (isset($this->factories[$id])) { + return $this->factories[$id](); + } if (isset($this->loading[$id])) { throw new ServiceCircularReferenceException($id, array_keys($this->loading)); @@ -296,7 +300,7 @@ class Container implements ResettableContainerInterface */ public function reset() { - $this->services = array(); + $this->services = $this->factories = array(); } /** diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index f500ecccac..893ba5d42e 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -713,7 +713,7 @@ EOTXT $lazyInitialization = ''; } - $asFile = $this->asFiles && $definition->isShared() && !$this->isHotPath($definition); + $asFile = $this->asFiles && !$this->isHotPath($definition); $methodName = $this->generateMethodName($id); if ($asFile) { $file = $methodName.'.php'; @@ -787,7 +787,7 @@ EOF; $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { - if ($definition->isSynthetic() || ($this->asFiles && $definition->isShared() && !$this->isHotPath($definition))) { + if ($definition->isSynthetic() || ($this->asFiles && !$this->isHotPath($definition))) { continue; } if ($definition->isPublic()) { @@ -805,8 +805,15 @@ EOF; $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { - if (!$definition->isSynthetic() && $definition->isShared() && !$this->isHotPath($definition)) { + if (!$definition->isSynthetic() && !$this->isHotPath($definition)) { $code = $this->addService($id, $definition, $file); + + if (!$definition->isShared()) { + $code = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $code))); + $factory = sprintf('$this->factories%s[\'%s\']', $definition->isPublic() ? '' : "['service_container']", $id); + $code = sprintf("\n%s = function () {\n%s};\n\nreturn %1\$s();\n", $factory, $code); + } + yield $file => $code; } } @@ -1038,7 +1045,7 @@ EOF; $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { - if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || !$definition->isShared() || $this->isHotPath($definition))) { + if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || $this->isHotPath($definition))) { $code .= ' '.$this->doExport($id).' => '.$this->doExport($this->generateMethodName($id)).",\n"; } } @@ -1052,7 +1059,7 @@ EOF; $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { - if (!$definition->isSynthetic() && $definition->isPublic() && $definition->isShared() && !$this->isHotPath($definition)) { + if (!$definition->isSynthetic() && $definition->isPublic() && !$this->isHotPath($definition)) { $code .= sprintf(" %s => __DIR__.'/%s.php',\n", $this->doExport($id), $this->generateMethodName($id)); } } @@ -1623,8 +1630,12 @@ EOF; if ($definition->isShared()) { $code = sprintf('$this->%s[\'%s\'] = %s', $definition->isPublic() ? 'services' : 'privates', $id, $code); } - } elseif ($this->asFiles && $definition->isShared() && !$this->isHotPath($definition)) { + } elseif ($this->asFiles && !$this->isHotPath($definition)) { $code = sprintf("\$this->load(__DIR__.'/%s.php')", $this->generateMethodName($id)); + if (!$definition->isShared()) { + $factory = sprintf('$this->factories%s[\'%s\']', $definition->isPublic() ? '' : "['service_container']", $id); + $code = sprintf('(isset(%s) ? %1$s() : %s)', $factory, $code); + } } else { $code = sprintf('$this->%s()', $this->generateMethodName($id)); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 5a3b5c888f..2527a006ac 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -179,6 +179,20 @@ $this->services['foo.baz'] = $instance = \BazClass::getInstance(); return $instance; + [Container%s/getFooBarService.php] => factories['foo_bar'] = function () { + // Returns the public 'foo_bar' service. + + return new \Bar\FooClass(($this->services['deprecated_service'] ?? $this->load(__DIR__.'/getDeprecatedServiceService.php'))); +}; + +return $this->factories['foo_bar'](); + [Container%s/getFooWithInlineService.php] => methodMap = array( 'bar' => 'getBarService', - 'foo_bar' => 'getFooBarService', ); $this->fileMap = array( 'BAR' => __DIR__.'/getBAR2Service.php', @@ -347,6 +360,7 @@ class ProjectServiceContainer extends Container 'factory_service_simple' => __DIR__.'/getFactoryServiceSimpleService.php', 'foo' => __DIR__.'/getFooService.php', 'foo.baz' => __DIR__.'/getFoo_BazService.php', + 'foo_bar' => __DIR__.'/getFooBarService.php', 'foo_with_inline' => __DIR__.'/getFooWithInlineService.php', 'lazy_context' => __DIR__.'/getLazyContextService.php', 'lazy_context_ignore_invalid_ref' => __DIR__.'/getLazyContextIgnoreInvalidRefService.php', @@ -404,16 +418,6 @@ class ProjectServiceContainer extends Container return $instance; } - /** - * Gets the public 'foo_bar' service. - * - * @return \Bar\FooClass - */ - protected function getFooBarService() - { - return new \Bar\FooClass(($this->services['deprecated_service'] ?? $this->load(__DIR__.'/getDeprecatedServiceService.php'))); - } - public function getParameter($name) { $name = (string) $name;