Skip to content

Commit

Permalink
[DI] generate preload.php file for PHP 7.4 in cache folder
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Jun 13, 2019
1 parent 567cb27 commit 85e1fec
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 20 deletions.
64 changes: 51 additions & 13 deletions src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
Expand Up @@ -32,6 +32,7 @@
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper;
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ServiceLocator as BaseServiceLocator;
use Symfony\Component\DependencyInjection\TypedReference;
Expand Down Expand Up @@ -216,7 +217,7 @@ public function dump(array $options = [])
}

$code =
$this->startClass($options['class'], $baseClass, $baseClassWithNamespace).
$this->startClass($options['class'], $baseClass, $baseClassWithNamespace, $preload).
$this->addServices($services).
$this->addDeprecatedAliases().
$this->addDefaultParametersMethod()
Expand All @@ -243,6 +244,10 @@ public function dump(array $options = [])
EOF;
$files = [];

if ($preload) {
$files['preload.php'] = "<?php\n".str_replace("\n include_once ", "\ninclude_once ", $preload)."\n";
}

$ids = $this->container->getRemovedIds();
foreach ($this->container->getDefinitions() as $id => $definition) {
if (!$definition->isPublic()) {
Expand Down Expand Up @@ -277,6 +282,34 @@ public function dump(array $options = [])
$time = $options['build_time'];
$id = hash('crc32', $hash.$time);

if ($preload) {
$preload = <<<EOF
<?php
// This file has been auto-generated by the Symfony Dependency Injection Component
// You can reference it in the "opcache.preload" php.ini setting on PHP >= 7.4 when preloading is desired
require __DIR__.'/Container{$hash}/preload.php';
EOF;

$lineage = [];

$this->collectLineage($baseClassWithNamespace, $lineage, true);
$this->collectLineage(EnvPlaceholderParameterBag::class, $lineage);

$lineage[] = "__DIR__.'/Container{$hash}/{$options['class']}.php'";

foreach ($lineage as $file) {
if (!isset($this->inlinedRequires[$file])) {
$this->inlinedRequires[$file] = true;
$preload .= sprintf("include_once %s;\n", preg_replace('#^\\$this->targetDirs\[(\d++)\]#', 'dirname(__DIR__, $1)', $file));
}
}

$code[$options['class'].'.preload.php'] = $preload;
}

$code[$options['class'].'.php'] = <<<EOF
<?php
{$namespaceLine}
Expand Down Expand Up @@ -391,15 +424,15 @@ private function connectCircularReferences($sourceId, &$currentPath, &$subPath =
unset($subPath[$sourceId]);
}

private function collectLineage($class, array &$lineage)
private function collectLineage($class, array &$lineage, bool $allowContainer = false)
{
if (isset($lineage[$class])) {
return;
}
if (!$r = $this->container->getReflectionClass($class, false)) {
return;
}
if ($this->container instanceof $class) {
if (!$allowContainer && $this->container instanceof $class) {
return;
}
$file = $r->getFileName();
Expand All @@ -408,15 +441,15 @@ private function collectLineage($class, array &$lineage)
}

if ($parent = $r->getParentClass()) {
$this->collectLineage($parent->name, $lineage);
$this->collectLineage($parent->name, $lineage, $allowContainer);
}

foreach ($r->getInterfaces() as $parent) {
$this->collectLineage($parent->name, $lineage);
$this->collectLineage($parent->name, $lineage, $allowContainer);
}

foreach ($r->getTraits() as $parent) {
$this->collectLineage($parent->name, $lineage);
$this->collectLineage($parent->name, $lineage, $allowContainer);
}

$lineage[$class] = substr($exportedFile, 1, -1);
Expand Down Expand Up @@ -474,13 +507,14 @@ private function addServiceInclude(string $cId, Definition $definition): string
}

foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) {
$code .= sprintf(" include_once %s;\n", $file);
$code .= sprintf(" include_once %s;\n", preg_replace('#^\\$this->targetDirs\[(\d++)\]#', sprintf('\dirname(__DIR__, %d + $1)', $this->asFiles), $file));
}
}

foreach ($this->inlinedDefinitions as $def) {
if ($file = $def->getFile()) {
$code .= sprintf(" include_once %s;\n", $this->dumpValue($file));
$file = $this->dumpValue($file);
$code .= sprintf(" include_once %s;\n", preg_replace('#^\\$this->targetDirs\[(\d++)\]#', sprintf('\dirname(__DIR__, %d + $1)', $this->asFiles), $file));
}
}

Expand Down Expand Up @@ -958,7 +992,7 @@ private function addNewInstance(Definition $definition, string $return = '', str
return $return.sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments)).$tail;
}

private function startClass(string $class, string $baseClass, string $baseClassWithNamespace): string
private function startClass(string $class, string $baseClass, string $baseClassWithNamespace, ?string &$preload): string
{
$namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : '';

Expand Down Expand Up @@ -1026,7 +1060,11 @@ public function __construct()
$code .= $this->addMethodMap();
$code .= $this->asFiles ? $this->addFileMap() : '';
$code .= $this->addAliases();
$code .= $this->addInlineRequires();

if ($preload = $this->getInlineRequires()) {
$code .= sprintf("\n \$this->privates['service_container'] = static function () {%s\n };\n", $this->asFiles ? "\n require_once __DIR__.'/preload.php';" : $preload);
}

$code .= <<<EOF
}
Expand Down Expand Up @@ -1227,7 +1265,7 @@ protected function {$methodNameAlias}()
return $code;
}

private function addInlineRequires(): string
private function getInlineRequires(): string
{
if (!$this->hotPathTag || !$this->inlineRequires) {
return '';
Expand All @@ -1251,11 +1289,11 @@ private function addInlineRequires(): string
foreach ($lineage as $file) {
if (!isset($this->inlinedRequires[$file])) {
$this->inlinedRequires[$file] = true;
$code .= sprintf("\n include_once %s;", $file);
$code .= sprintf("\n include_once %s;", preg_replace('#^\\$this->targetDirs\[(\d++)\]#', sprintf('\dirname(__DIR__, %d + $1)', $this->asFiles), $file));
}
}

return $code ? sprintf("\n \$this->privates['service_container'] = function () {%s\n };\n", $code) : '';
return $code;
}

private function addDefaultParametersMethod(): string
Expand Down
Expand Up @@ -36,11 +36,11 @@ public function __construct()

$this->aliases = [];

$this->privates['service_container'] = function () {
include_once $this->targetDirs[1].'/includes/HotPath/I1.php';
include_once $this->targetDirs[1].'/includes/HotPath/P1.php';
include_once $this->targetDirs[1].'/includes/HotPath/T1.php';
include_once $this->targetDirs[1].'/includes/HotPath/C1.php';
$this->privates['service_container'] = static function () {
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/I1.php';
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/P1.php';
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/T1.php';
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/C1.php';
};
}

Expand Down Expand Up @@ -90,8 +90,8 @@ protected function getC1Service()
*/
protected function getC2Service()
{
include_once $this->targetDirs[1].'/includes/HotPath/C2.php';
include_once $this->targetDirs[1].'/includes/HotPath/C3.php';
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/C2.php';
include_once \dirname(__DIR__, 0 + 1).'/includes/HotPath/C3.php';

return $this->services['Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\includes\\HotPath\\C2'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C2(new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3());
}
Expand Down

0 comments on commit 85e1fec

Please sign in to comment.