feature #32581 [DI] Allow dumping the container in one file instead of many files (nicolas-grekas)

This PR was merged into the 4.4 branch.

Discussion
----------

[DI] Allow dumping the container in one file instead of many files

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

Replaces #32119
As spotted by @lyrixx, putting all service factories in one big container can be easier to manage with workers. It could also play well with PHP7.4's preloading.

This PR adds a `container.dumper.inline_factories` parameter to enable this behavior.
When it is set to true, a single big container file is created.

Commits
-------

c893986815 [DI] Allow dumping the container in one file instead of many files
This commit is contained in:
Nicolas Grekas 2019-07-31 18:42:55 +02:00
commit 85058f5810
5 changed files with 901 additions and 23 deletions

View File

@ -4,6 +4,7 @@ CHANGELOG
4.4.0
-----
* added support for dumping the container in one file instead of many files
* deprecated support for short factories and short configurators in Yaml
* deprecated `tagged` in favor of `tagged_iterator`
* deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition`

View File

@ -72,6 +72,7 @@ class PhpDumper extends Dumper
private $namespace;
private $asFiles;
private $hotPathTag;
private $inlineFactories;
private $inlineRequires;
private $inlinedRequires = [];
private $circularReferences = [];
@ -134,6 +135,7 @@ class PhpDumper extends Dumper
'as_files' => false,
'debug' => true,
'hot_path_tag' => 'container.hot_path',
'inline_factories_parameter' => 'container.dumper.inline_factories',
'inline_class_loader_parameter' => 'container.dumper.inline_class_loader',
'service_locator_tag' => 'container.service_locator',
'build_time' => time(),
@ -143,6 +145,7 @@ class PhpDumper extends Dumper
$this->namespace = $options['namespace'];
$this->asFiles = $options['as_files'];
$this->hotPathTag = $options['hot_path_tag'];
$this->inlineFactories = $this->asFiles && $options['inline_factories_parameter'] && $this->container->hasParameter($options['inline_factories_parameter']) && $this->container->getParameter($options['inline_factories_parameter']);
$this->inlineRequires = $options['inline_class_loader_parameter'] && $this->container->hasParameter($options['inline_class_loader_parameter']) && $this->container->getParameter($options['inline_class_loader_parameter']);
$this->serviceLocatorTag = $options['service_locator_tag'];
@ -216,6 +219,8 @@ class PhpDumper extends Dumper
}
}
$proxyClasses = $this->inlineFactories ? $this->generateProxyClasses() : null;
$code =
$this->startClass($options['class'], $baseClass, $baseClassWithNamespace).
$this->addServices($services).
@ -223,6 +228,8 @@ class PhpDumper extends Dumper
$this->addDefaultParametersMethod()
;
$proxyClasses = $proxyClasses ?? $this->generateProxyClasses();
if ($this->addGetService) {
$code = preg_replace(
"/(\r?\n\r?\n public function __construct.+?\\{\r?\n)/s",
@ -259,13 +266,24 @@ EOF;
$files['removed-ids.php'] = $c .= "];\n";
}
foreach ($this->generateServiceFiles($services) as $file => $c) {
$files[$file] = $fileStart.$c;
if (!$this->inlineFactories) {
foreach ($this->generateServiceFiles($services) as $file => $c) {
$files[$file] = $fileStart.$c;
}
foreach ($proxyClasses as $file => $c) {
$files[$file] = "<?php\n".$c;
}
}
foreach ($this->generateProxyClasses() as $file => $c) {
$files[$file] = "<?php\n".$c;
$code .= $this->endClass();
if ($this->inlineFactories) {
foreach ($proxyClasses as $c) {
$code .= $c;
}
}
$files[$options['class'].'.php'] = $code.$this->endClass();
$files[$options['class'].'.php'] = $code;
$hash = ucfirst(strtr(ContainerBuilder::hash($files), '._', 'xx'));
$code = [];
@ -304,7 +322,7 @@ return new \\Container{$hash}\\{$options['class']}([
EOF;
} else {
$code .= $this->endClass();
foreach ($this->generateProxyClasses() as $c) {
foreach ($proxyClasses as $c) {
$code .= $c;
}
}
@ -431,8 +449,9 @@ EOF;
$lineage[$class] = substr($exportedFile, 1, -1);
}
private function generateProxyClasses()
private function generateProxyClasses(): array
{
$proxyClasses = [];
$alreadyGenerated = [];
$definitions = $this->container->getDefinitions();
$strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments');
@ -451,19 +470,39 @@ EOF;
if ("\n" === $proxyCode = "\n".$proxyDumper->getProxyCode($definition)) {
continue;
}
if ($this->inlineRequires) {
$lineage = [];
$this->collectLineage($class, $lineage);
$code = '';
foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) {
if ($this->inlineFactories) {
$this->inlinedRequires[$file] = true;
}
$file = preg_replace('#^\\$this->targetDirs\[(\d++)\]#', sprintf('\dirname(__DIR__, %d + $1)', $this->asFiles), $file);
$code .= sprintf("include_once %s;\n", $file);
}
$proxyCode = $code.$proxyCode;
}
if ($strip) {
$proxyCode = "<?php\n".$proxyCode;
$proxyCode = substr(Kernel::stripComments($proxyCode), 5);
}
yield sprintf('%s.php', explode(' ', $proxyCode, 3)[1]) => $proxyCode;
$proxyClasses[sprintf('%s.php', explode(' ', $proxyCode, 3)[1])] = $proxyCode;
}
return $proxyClasses;
}
private function addServiceInclude(string $cId, Definition $definition): string
{
$code = '';
if ($this->inlineRequires && !$this->isHotPath($definition)) {
if ($this->inlineRequires && (!$this->isHotPath($definition) || $this->getProxyDumper()->isProxyCandidate($definition))) {
$lineage = [];
foreach ($this->inlinedDefinitions as $def) {
if (!$def->isDeprecated() && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) {
@ -693,7 +732,7 @@ EOF;
$lazyInitialization = '';
}
$asFile = $this->asFiles && !$this->isHotPath($definition);
$asFile = $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition);
$methodName = $this->generateMethodName($id);
if ($asFile) {
$file = $methodName.'.php';
@ -719,17 +758,16 @@ EOF;
$this->serviceCalls = [];
$this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls);
$code .= $this->addServiceInclude($id, $definition);
if ($definition->isDeprecated()) {
$code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id)));
}
if ($this->getProxyDumper()->isProxyCandidate($definition)) {
$factoryCode = $asFile ? ($definition->isShared() ? "\$this->load('%s.php', false)" : '$this->factories[%2$s](false)') : '$this->%s(false)';
$code .= $this->getProxyDumper()->getProxyFactoryCode($definition, $id, sprintf($factoryCode, $methodName, $this->doExport($id)));
}
if ($definition->isDeprecated()) {
$code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id)));
}
$code .= $this->addServiceInclude($id, $definition);
$code .= $this->addInlineService($id, $definition);
if ($asFile) {
@ -1044,7 +1082,7 @@ EOF;
$code .= $this->addSyntheticIds();
$code .= $this->addMethodMap();
$code .= $this->asFiles ? $this->addFileMap() : '';
$code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : '';
$code .= $this->addAliases();
$code .= $this->addInlineRequires();
$code .= <<<EOF
@ -1063,7 +1101,7 @@ EOF;
EOF;
$code .= $this->addRemovedIds();
if ($this->asFiles) {
if ($this->asFiles && !$this->inlineFactories) {
$code .= <<<EOF
protected function load(\$file, \$lazyLoad = true)
@ -1079,10 +1117,10 @@ EOF;
if (!$proxyDumper->isProxyCandidate($definition)) {
continue;
}
if ($this->asFiles) {
if ($this->asFiles && !$this->inlineFactories) {
$proxyLoader = '$this->load("{$class}.php")';
} elseif ($this->namespace) {
$proxyLoader = 'class_alias("'.$this->namespace.'\\\\{$class}", $class, false)';
} elseif ($this->namespace || $this->inlineFactories) {
$proxyLoader = 'class_alias(__NAMESPACE__."\\\\$class", $class, false)';
} else {
$proxyLoader = '';
}
@ -1160,7 +1198,7 @@ EOF;
$definitions = $this->container->getDefinitions();
ksort($definitions);
foreach ($definitions as $id => $definition) {
if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || $this->isHotPath($definition))) {
if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || $this->inlineFactories || $this->isHotPath($definition))) {
$code .= ' '.$this->doExport($id).' => '.$this->doExport($this->generateMethodName($id)).",\n";
}
}
@ -1257,6 +1295,11 @@ EOF;
foreach ($this->container->findTaggedServiceIds($this->hotPathTag) as $id => $tags) {
$definition = $this->container->getDefinition($id);
if ($this->getProxyDumper()->isProxyCandidate($definition)) {
continue;
}
$inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]);
foreach ($inlinedDefinitions as $def) {
@ -1604,7 +1647,7 @@ EOF;
continue;
}
$definition = $this->container->findDefinition($id = (string) $v);
$load = !($definition->hasErrors() && $e = $definition->getErrors()) ? $this->asFiles && !$this->isHotPath($definition) : reset($e);
$load = !($definition->hasErrors() && $e = $definition->getErrors()) ? $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition) : reset($e);
$serviceMap .= sprintf("\n %s => [%s, %s, %s, %s],",
$this->export($k),
$this->export($definition->isShared() ? ($definition->isPublic() ? 'services' : 'privates') : false),
@ -1747,7 +1790,7 @@ EOF;
$code = sprintf('$this->%s[%s] = %s', $definition->isPublic() ? 'services' : 'privates', $this->doExport($id), $code);
}
$code = "($code)";
} elseif ($this->asFiles && !$this->isHotPath($definition)) {
} elseif ($this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition)) {
$code = sprintf("\$this->load('%s.php')", $this->generateMethodName($id));
if (!$definition->isShared()) {
$factory = sprintf('$this->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id));

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Dumper;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
@ -42,6 +43,8 @@ use Symfony\Component\ExpressionLanguage\Expression;
require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php';
require_once __DIR__.'/../Fixtures/includes/classes.php';
require_once __DIR__.'/../Fixtures/includes/foo.php';
require_once __DIR__.'/../Fixtures/includes/foo_lazy.php';
class PhpDumperTest extends TestCase
{
@ -234,6 +237,59 @@ class PhpDumperTest extends TestCase
$this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_as_files.txt', $dump);
}
public function testDumpAsFilesWithFactoriesInlined()
{
$container = include self::$fixturesPath.'/containers/container9.php';
$container->setParameter('container.dumper.inline_factories', true);
$container->setParameter('container.dumper.inline_class_loader', true);
$container->getDefinition('bar')->addTag('hot');
$container->register('non_shared_foo', \Bar\FooClass::class)
->setFile(realpath(self::$fixturesPath.'/includes/foo.php'))
->setShared(false)
->setPublic(true);
$container->register('throwing_one', \Bar\FooClass::class)
->addArgument(new Reference('errored_one', ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE))
->setPublic(true);
$container->register('errored_one', 'stdClass')
->addError('No-no-no-no');
$container->compile();
$dumper = new PhpDumper($container);
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'build_time' => 1563381341]), true);
if ('\\' === \DIRECTORY_SEPARATOR) {
$dump = str_replace('\\\\Fixtures\\\\includes\\\\', '/Fixtures/includes/', $dump);
}
$this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_inlined_factories.txt', $dump);
}
/**
* @requires function \Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper::getProxyCode
*/
public function testDumpAsFilesWithLazyFactoriesInlined()
{
$container = new ContainerBuilder();
$container->setParameter('container.dumper.inline_factories', true);
$container->setParameter('container.dumper.inline_class_loader', true);
$container->register('lazy_foo', \Bar\FooClass::class)
->addArgument(new Definition(\Bar\FooLazyClass::class))
->setPublic(true)
->setLazy(true);
$container->compile();
$dumper = new PhpDumper($container);
$dumper->setProxyDumper(new ProxyDumper());
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'build_time' => 1563381341]), true);
if ('\\' === \DIRECTORY_SEPARATOR) {
$dump = str_replace('\\\\Fixtures\\\\includes\\\\', '/Fixtures/includes/', $dump);
}
$this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_lazy_inlined_factories.txt', $dump);
}
public function testNonSharedLazyDumpAsFiles()
{
$container = include self::$fixturesPath.'/containers/container_non_shared_lazy.php';

View File

@ -0,0 +1,572 @@
Array
(
[Container%s/removed-ids.php] => <?php
return [
'Psr\\Container\\ContainerInterface' => true,
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
'configurator_service' => true,
'configurator_service_simple' => true,
'decorated.pif-pouf' => true,
'decorator_service.inner' => true,
'errored_definition' => true,
'errored_one' => true,
'factory_simple' => true,
'inlined' => true,
'new_factory' => true,
'tagged_iterator_foo' => true,
];
[Container%s/ProjectServiceContainer.php] => <?php
namespace Container%s;
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
/**
* This class has been auto-generated
* by the Symfony Dependency Injection Component.
*
* @final since Symfony 3.3
*/
class ProjectServiceContainer extends Container
{
private $buildParameters;
private $containerDir;
private $parameters;
private $targetDirs = [];
public function __construct(array $buildParameters = [], $containerDir = __DIR__)
{
$dir = $this->targetDirs[0] = \dirname($containerDir);
for ($i = 1; $i <= 5; ++$i) {
$this->targetDirs[$i] = $dir = \dirname($dir);
}
$this->buildParameters = $buildParameters;
$this->containerDir = $containerDir;
$this->parameters = $this->getDefaultParameters();
$this->services = $this->privates = [];
$this->syntheticIds = [
'request' => true,
];
$this->methodMap = [
'BAR' => 'getBARService',
'BAR2' => 'getBAR2Service',
'bar' => 'getBar3Service',
'bar2' => 'getBar22Service',
'baz' => 'getBazService',
'configured_service' => 'getConfiguredServiceService',
'configured_service_simple' => 'getConfiguredServiceSimpleService',
'decorator_service' => 'getDecoratorServiceService',
'decorator_service_with_name' => 'getDecoratorServiceWithNameService',
'deprecated_service' => 'getDeprecatedServiceService',
'factory_service' => 'getFactoryServiceService',
'factory_service_simple' => 'getFactoryServiceSimpleService',
'foo' => 'getFooService',
'foo.baz' => 'getFoo_BazService',
'foo_bar' => 'getFooBarService',
'foo_with_inline' => 'getFooWithInlineService',
'lazy_context' => 'getLazyContextService',
'lazy_context_ignore_invalid_ref' => 'getLazyContextIgnoreInvalidRefService',
'method_call1' => 'getMethodCall1Service',
'new_factory_service' => 'getNewFactoryServiceService',
'non_shared_foo' => 'getNonSharedFooService',
'runtime_error' => 'getRuntimeErrorService',
'service_from_static_method' => 'getServiceFromStaticMethodService',
'tagged_iterator' => 'getTaggedIteratorService',
'throwing_one' => 'getThrowingOneService',
];
$this->aliases = [
'alias_for_alias' => 'foo',
'alias_for_foo' => 'foo',
'decorated' => 'decorator_service_with_name',
];
$this->privates['service_container'] = function () {
include_once $this->targetDirs[0].'/Fixtures/includes/foo.php';
};
}
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
public function isCompiled()
{
return true;
}
public function getRemovedIds()
{
return require $this->containerDir.\DIRECTORY_SEPARATOR.'removed-ids.php';
}
/**
* Gets the public 'BAR' shared service.
*
* @return \stdClass
*/
protected function getBARService()
{
$this->services['BAR'] = $instance = new \stdClass();
$instance->bar = ($this->services['bar'] ?? $this->getBar3Service());
return $instance;
}
/**
* Gets the public 'BAR2' shared service.
*
* @return \stdClass
*/
protected function getBAR2Service()
{
return $this->services['BAR2'] = new \stdClass();
}
/**
* Gets the public 'bar' shared service.
*
* @return \Bar\FooClass
*/
protected function getBar3Service()
{
$a = ($this->services['foo.baz'] ?? $this->getFoo_BazService());
$this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar'));
$a->configure($instance);
return $instance;
}
/**
* Gets the public 'bar2' shared service.
*
* @return \stdClass
*/
protected function getBar22Service()
{
return $this->services['bar2'] = new \stdClass();
}
/**
* Gets the public 'baz' shared service.
*
* @return \Baz
*/
protected function getBazService()
{
$this->services['baz'] = $instance = new \Baz();
$instance->setFoo(($this->services['foo_with_inline'] ?? $this->getFooWithInlineService()));
return $instance;
}
/**
* Gets the public 'configured_service' shared service.
*
* @return \stdClass
*/
protected function getConfiguredServiceService()
{
$this->services['configured_service'] = $instance = new \stdClass();
$a = new \ConfClass();
$a->setFoo(($this->services['baz'] ?? $this->getBazService()));
$a->configureStdClass($instance);
return $instance;
}
/**
* Gets the public 'configured_service_simple' shared service.
*
* @return \stdClass
*/
protected function getConfiguredServiceSimpleService()
{
$this->services['configured_service_simple'] = $instance = new \stdClass();
(new \ConfClass('bar'))->configureStdClass($instance);
return $instance;
}
/**
* Gets the public 'decorator_service' shared service.
*
* @return \stdClass
*/
protected function getDecoratorServiceService()
{
return $this->services['decorator_service'] = new \stdClass();
}
/**
* Gets the public 'decorator_service_with_name' shared service.
*
* @return \stdClass
*/
protected function getDecoratorServiceWithNameService()
{
return $this->services['decorator_service_with_name'] = new \stdClass();
}
/**
* Gets the public 'deprecated_service' shared service.
*
* @return \stdClass
*
* @deprecated The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.
*/
protected function getDeprecatedServiceService()
{
@trigger_error('The "deprecated_service" service is deprecated. You should stop using it, as it will be removed in the future.', E_USER_DEPRECATED);
return $this->services['deprecated_service'] = new \stdClass();
}
/**
* Gets the public 'factory_service' shared service.
*
* @return \Bar
*/
protected function getFactoryServiceService()
{
return $this->services['factory_service'] = ($this->services['foo.baz'] ?? $this->getFoo_BazService())->getInstance();
}
/**
* Gets the public 'factory_service_simple' shared service.
*
* @return \Bar
*/
protected function getFactoryServiceSimpleService()
{
return $this->services['factory_service_simple'] = $this->getFactorySimpleService()->getInstance();
}
/**
* Gets the public 'foo' shared service.
*
* @return \Bar\FooClass
*/
protected function getFooService()
{
$a = ($this->services['foo.baz'] ?? $this->getFoo_BazService());
$this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, ['bar' => 'foo is bar', 'foobar' => 'bar'], true, $this);
$instance->foo = 'bar';
$instance->moo = $a;
$instance->qux = ['bar' => 'foo is bar', 'foobar' => 'bar'];
$instance->setBar(($this->services['bar'] ?? $this->getBar3Service()));
$instance->initialize();
sc_configure($instance);
return $instance;
}
/**
* Gets the public 'foo.baz' shared service.
*
* @return \BazClass
*/
protected function getFoo_BazService()
{
include_once $this->targetDirs[0].'/Fixtures/includes/classes.php';
$this->services['foo.baz'] = $instance = \BazClass::getInstance();
\BazClass::configureStatic1($instance);
return $instance;
}
/**
* Gets the public 'foo_bar' service.
*
* @return \Bar\FooClass
*/
protected function getFooBarService()
{
return new \Bar\FooClass(($this->services['deprecated_service'] ?? $this->getDeprecatedServiceService()));
}
/**
* Gets the public 'foo_with_inline' shared service.
*
* @return \Foo
*/
protected function getFooWithInlineService()
{
$this->services['foo_with_inline'] = $instance = new \Foo();
$a = new \Bar();
$a->pub = 'pub';
$a->setBaz(($this->services['baz'] ?? $this->getBazService()));
$instance->setBar($a);
return $instance;
}
/**
* Gets the public 'lazy_context' shared service.
*
* @return \LazyContext
*/
protected function getLazyContextService()
{
include_once $this->targetDirs[0].'/Fixtures/includes/classes.php';
return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () {
yield 'k1' => ($this->services['foo.baz'] ?? $this->getFoo_BazService());
yield 'k2' => $this;
}, 2), new RewindableGenerator(function () {
return new \EmptyIterator();
}, 0));
}
/**
* Gets the public 'lazy_context_ignore_invalid_ref' shared service.
*
* @return \LazyContext
*/
protected function getLazyContextIgnoreInvalidRefService()
{
include_once $this->targetDirs[0].'/Fixtures/includes/classes.php';
return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () {
yield 0 => ($this->services['foo.baz'] ?? $this->getFoo_BazService());
}, 1), new RewindableGenerator(function () {
return new \EmptyIterator();
}, 0));
}
/**
* Gets the public 'method_call1' shared service.
*
* @return \Bar\FooClass
*/
protected function getMethodCall1Service()
{
include_once ($this->targetDirs[0].'/Fixtures/includes/foo.php');
$this->services['method_call1'] = $instance = new \Bar\FooClass();
$instance->setBar(($this->services['foo'] ?? $this->getFooService()));
$instance->setBar(NULL);
$instance->setBar((($this->services['foo'] ?? $this->getFooService())->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default"))));
return $instance;
}
/**
* Gets the public 'new_factory_service' shared service.
*
* @return \FooBarBaz
*/
protected function getNewFactoryServiceService()
{
$a = new \FactoryClass();
$a->foo = 'bar';
$this->services['new_factory_service'] = $instance = $a->getInstance();
$instance->foo = 'bar';
return $instance;
}
/**
* Gets the public 'non_shared_foo' service.
*
* @return \Bar\FooClass
*/
protected function getNonSharedFooService()
{
include_once ($this->targetDirs[0].'/Fixtures/includes/foo.php');
return new \Bar\FooClass();
}
/**
* Gets the public 'runtime_error' shared service.
*
* @return \stdClass
*/
protected function getRuntimeErrorService()
{
return $this->services['runtime_error'] = new \stdClass($this->throw('Service "errored_definition" is broken.'));
}
/**
* Gets the public 'service_from_static_method' shared service.
*
* @return \Bar\FooClass
*/
protected function getServiceFromStaticMethodService()
{
return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance();
}
/**
* Gets the public 'tagged_iterator' shared service.
*
* @return \Bar
*/
protected function getTaggedIteratorService()
{
return $this->services['tagged_iterator'] = new \Bar(new RewindableGenerator(function () {
yield 0 => ($this->services['foo'] ?? $this->getFooService());
yield 1 => ($this->privates['tagged_iterator_foo'] ?? ($this->privates['tagged_iterator_foo'] = new \Bar()));
}, 2));
}
/**
* Gets the public 'throwing_one' shared service.
*
* @return \Bar\FooClass
*/
protected function getThrowingOneService()
{
return $this->services['throwing_one'] = new \Bar\FooClass($this->throw('No-no-no-no'));
}
/**
* Gets the private 'factory_simple' shared service.
*
* @return \SimpleFactoryClass
*
* @deprecated The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.
*/
protected function getFactorySimpleService()
{
@trigger_error('The "factory_simple" service is deprecated. You should stop using it, as it will be removed in the future.', E_USER_DEPRECATED);
return new \SimpleFactoryClass('foo');
}
public function getParameter($name)
{
$name = (string) $name;
if (isset($this->buildParameters[$name])) {
return $this->buildParameters[$name];
}
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
}
if (isset($this->loadedDynamicParameters[$name])) {
return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
}
return $this->parameters[$name];
}
public function hasParameter($name)
{
$name = (string) $name;
if (isset($this->buildParameters[$name])) {
return true;
}
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
public function getParameterBag()
{
if (null === $this->parameterBag) {
$parameters = $this->parameters;
foreach ($this->loadedDynamicParameters as $name => $loaded) {
$parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
}
foreach ($this->buildParameters as $name => $value) {
$parameters[$name] = $value;
}
$this->parameterBag = new FrozenParameterBag($parameters);
}
return $this->parameterBag;
}
private $loadedDynamicParameters = [];
private $dynamicParameters = [];
/**
* Computes a dynamic parameter.
*
* @param string $name The name of the dynamic parameter to load
*
* @return mixed The value of the dynamic parameter
*
* @throws InvalidArgumentException When the dynamic parameter does not exist
*/
private function getDynamicParameter($name)
{
throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
}
/**
* Gets the default parameters.
*
* @return array An array of the default parameters
*/
protected function getDefaultParameters()
{
return [
'baz_class' => 'BazClass',
'foo_class' => 'Bar\\FooClass',
'foo' => 'bar',
'container.dumper.inline_factories' => true,
'container.dumper.inline_class_loader' => true,
];
}
protected function throw($message)
{
throw new RuntimeException($message);
}
}
[ProjectServiceContainer.php] => <?php
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
if (\class_exists(\Container%s\ProjectServiceContainer::class, false)) {
// no-op
} elseif (!include __DIR__.'/Container%s/ProjectServiceContainer.php') {
touch(__DIR__.'/Container%s.legacy');
return;
}
if (!\class_exists(ProjectServiceContainer::class, false)) {
\class_alias(\Container%s\ProjectServiceContainer::class, ProjectServiceContainer::class, false);
}
return new \Container%s\ProjectServiceContainer([
'container.build_hash' => '%s',
'container.build_id' => '%s',
'container.build_time' => 1563381341,
], __DIR__.\DIRECTORY_SEPARATOR.'Container%s');
)

View File

@ -0,0 +1,206 @@
Array
(
[Container%s/removed-ids.php] => <?php
return [
'Psr\\Container\\ContainerInterface' => true,
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
];
[Container%s/ProjectServiceContainer.php] => <?php
namespace Container%s;
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
/**
* This class has been auto-generated
* by the Symfony Dependency Injection Component.
*
* @final since Symfony 3.3
*/
class ProjectServiceContainer extends Container
{
private $buildParameters;
private $containerDir;
private $parameters;
private $targetDirs = [];
public function __construct(array $buildParameters = [], $containerDir = __DIR__)
{
$dir = $this->targetDirs[0] = \dirname($containerDir);
for ($i = 1; $i <= 5; ++$i) {
$this->targetDirs[$i] = $dir = \dirname($dir);
}
$this->buildParameters = $buildParameters;
$this->containerDir = $containerDir;
$this->parameters = $this->getDefaultParameters();
$this->services = $this->privates = [];
$this->methodMap = [
'lazy_foo' => 'getLazyFooService',
];
$this->aliases = [];
}
public function compile()
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
public function isCompiled()
{
return true;
}
public function getRemovedIds()
{
return require $this->containerDir.\DIRECTORY_SEPARATOR.'removed-ids.php';
}
protected function createProxy($class, \Closure $factory)
{
class_exists($class, false) || class_alias(__NAMESPACE__."\\$class", $class, false);
return $factory();
}
/**
* Gets the public 'lazy_foo' shared service.
*
* @return \Bar\FooClass
*/
protected function getLazyFooService($lazyLoad = true)
{
if ($lazyLoad) {
return $this->services['lazy_foo'] = $this->createProxy('FooClass_%s', function () {
return \FooClass_%s::staticProxyConstructor(function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {
$wrappedInstance = $this->getLazyFooService(false);
$proxy->setProxyInitializer(null);
return true;
});
});
}
include_once $this->targetDirs[0].'/Fixtures/includes/foo_lazy.php';
return new \Bar\FooClass(new \Bar\FooLazyClass());
}
public function getParameter($name)
{
$name = (string) $name;
if (isset($this->buildParameters[$name])) {
return $this->buildParameters[$name];
}
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
}
if (isset($this->loadedDynamicParameters[$name])) {
return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
}
return $this->parameters[$name];
}
public function hasParameter($name)
{
$name = (string) $name;
if (isset($this->buildParameters[$name])) {
return true;
}
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
}
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
public function getParameterBag()
{
if (null === $this->parameterBag) {
$parameters = $this->parameters;
foreach ($this->loadedDynamicParameters as $name => $loaded) {
$parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
}
foreach ($this->buildParameters as $name => $value) {
$parameters[$name] = $value;
}
$this->parameterBag = new FrozenParameterBag($parameters);
}
return $this->parameterBag;
}
private $loadedDynamicParameters = [];
private $dynamicParameters = [];
/**
* Computes a dynamic parameter.
*
* @param string $name The name of the dynamic parameter to load
*
* @return mixed The value of the dynamic parameter
*
* @throws InvalidArgumentException When the dynamic parameter does not exist
*/
private function getDynamicParameter($name)
{
throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
}
/**
* Gets the default parameters.
*
* @return array An array of the default parameters
*/
protected function getDefaultParameters()
{
return [
'container.dumper.inline_factories' => true,
'container.dumper.inline_class_loader' => true,
];
}
}
include_once \dirname(__DIR__, 1 + 0).'/Fixtures/includes/foo.php';
class FooClass_%s extends \Bar\FooClass implements \ProxyManager\Proxy\VirtualProxyInterface
{
%A
}
[ProjectServiceContainer.php] => <?php
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
if (\class_exists(\Container%s\ProjectServiceContainer::class, false)) {
// no-op
} elseif (!include __DIR__.'/Container%s/ProjectServiceContainer.php') {
touch(__DIR__.'/Container%s.legacy');
return;
}
if (!\class_exists(ProjectServiceContainer::class, false)) {
\class_alias(\Container%s\ProjectServiceContainer::class, ProjectServiceContainer::class, false);
}
return new \Container%s\ProjectServiceContainer([
'container.build_hash' => '%s',
'container.build_id' => '%s',
'container.build_time' => 1563381341,
], __DIR__.\DIRECTORY_SEPARATOR.'Container%s');
)