Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/Symfony/Component/HttpKernel/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ CHANGELOG
* Implementing the `BundleInterface` without implementing the `getPublicDir()` method is deprecated.
This method will be added to the interface in 5.0.
* The `DebugHandlersListener` class has been marked as `final`
* Add support for dumping the container in one file instead of many files

4.3.0
-----
Expand Down Expand Up @@ -38,8 +39,8 @@ CHANGELOG

* deprecated `KernelInterface::getRootDir()` and the `kernel.root_dir` parameter
* deprecated `KernelInterface::getName()` and the `kernel.name` parameter
* deprecated the first and second constructor argument of `ConfigDataCollector`
* deprecated `ConfigDataCollector::getApplicationName()`
* deprecated the first and second constructor argument of `ConfigDataCollector`
* deprecated `ConfigDataCollector::getApplicationName()`
* deprecated `ConfigDataCollector::getApplicationVersion()`

4.1.0
Expand Down
57 changes: 36 additions & 21 deletions src/Symfony/Component/HttpKernel/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -479,30 +479,34 @@ protected function getContainerBaseClass()
*/
protected function initializeContainer()
{
$asFiles = $this->getKernelParameters()['container.dump_as_files'] ?? true;
$class = $this->getContainerClass();
$cacheDir = $this->warmupDir ?: $this->getCacheDir();
$cache = new ConfigCache($cacheDir.'/'.$class.'.php', $this->debug);
$oldContainer = null;
if ($fresh = $cache->isFresh()) {
if ($cache->isFresh()) {
// Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors
$errorLevel = error_reporting(\E_ALL ^ \E_WARNING);
$fresh = $oldContainer = false;
$oldContainer = false;
try {
if (!$asFiles) {
require_once $cache->getPath();
$this->container = new $class();
$this->container->set('kernel', $this);

return;
}
if (file_exists($cache->getPath()) && \is_object($this->container = include $cache->getPath())) {
$this->container->set('kernel', $this);
$oldContainer = $this->container;
$fresh = true;

return;
}
} catch (\Throwable $e) {
} finally {
error_reporting($errorLevel);
}
}

if ($fresh) {
return;
}

if ($this->debug) {
$collectedLogs = [];
$previousHandler = \defined('PHPUNIT_COMPOSER_INSTALL');
Expand Down Expand Up @@ -557,7 +561,7 @@ protected function initializeContainer()
}
}

if (null === $oldContainer && file_exists($cache->getPath())) {
if ($asFiles && null === $oldContainer && file_exists($cache->getPath())) {
$errorLevel = error_reporting(\E_ALL ^ \E_WARNING);
try {
$oldContainer = include $cache->getPath();
Expand All @@ -569,7 +573,12 @@ protected function initializeContainer()
$oldContainer = \is_object($oldContainer) ? new \ReflectionClass($oldContainer) : false;

$this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
$this->container = require $cache->getPath();
if ($asFiles) {
$this->container = require $cache->getPath();
} else {
require $cache->getPath();
$this->container = new $class();
}
$this->container->set('kernel', $this);

if ($oldContainer && \get_class($this->container) !== $oldContainer->name) {
Expand Down Expand Up @@ -731,26 +740,32 @@ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container
$dumper->setProxyDumper(new ProxyDumper());
}

$asFiles = $container->hasParameter('container.dump_as_files') ? $container->getParameter('container.dump_as_files') : true;

$content = $dumper->dump([
'class' => $class,
'base_class' => $baseClass,
'file' => $cache->getPath(),
'as_files' => true,
'as_files' => $asFiles,
'debug' => $this->debug,
'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(),
]);

$rootCode = array_pop($content);
$dir = \dirname($cache->getPath()).'/';
$fs = new Filesystem();
if ($asFiles) {
$rootCode = array_pop($content);
$dir = \dirname($cache->getPath()).'/';
$fs = new Filesystem();

foreach ($content as $file => $code) {
$fs->dumpFile($dir.$file, $code);
@chmod($dir.$file, 0666 & ~umask());
}
$legacyFile = \dirname($dir.$file).'.legacy';
if (file_exists($legacyFile)) {
@unlink($legacyFile);
foreach ($content as $file => $code) {
$fs->dumpFile($dir.$file, $code);
@chmod($dir.$file, 0666 & ~umask());
}
$legacyFile = \dirname($dir.$file).'.legacy';
if (file_exists($legacyFile)) {
@unlink($legacyFile);
}
} else {
$rootCode = $content;
}

$cache->write($rootCode, $container->getResources());
Expand Down
38 changes: 38 additions & 0 deletions src/Symfony/Component/HttpKernel/Tests/KernelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ public function testInitializeContainerClearsOldContainers()
$this->assertFileNotExists($legacyContainerDir.'.legacy');
}

public function testKernelWithOneFileContainer()
{
$kernel = new KernelWithOneFileContainer('dev', true);
$kernel->boot();

$this->assertNotNull($kernel->getContainer());

$kernel->shutdown();
$kernel->boot();
$this->assertNotNull($kernel->getContainer());
}

public function testBootInitializesBundlesAndContainer()
{
$kernel = $this->getKernel(['initializeBundles', 'initializeContainer']);
Expand Down Expand Up @@ -775,3 +787,29 @@ public function process(ContainerBuilder $container)
$container->setParameter('test.processed', true);
}
}

class KernelWithOneFileContainer extends Kernel
{
public function registerBundles()
{
return [];
}

public function registerContainerConfiguration(LoaderInterface $loader)
{
}

public function getProjectDir()
{
return __DIR__.'/Fixtures';
}

protected function getKernelParameters()
{
return array_merge(parent::getKernelParameters(), [
'container.build_id' => 'static',
'container.build_hash' => 'static',
'container.dump_as_files' => false,
]);
}
}