bug #38357 [DI] fix dumping non-shared lazy services (nicolas-grekas)
This PR was merged into the 5.1 branch.
Discussion
----------
[DI] fix dumping non-shared lazy services
| Q | A
| ------------- | ---
| Branch? | 5.1
| Bug fix? | yes
| New feature? | no
| Deprecations? | no
| Tickets | Fix #38327
| License | MIT
| Doc PR | -
It took me a while to get this correct, but here we are.
Commits
-------
e33a0b0f94
[DI] fix dumping non-shared lazy services
This commit is contained in:
commit
e36a36ae27
@ -863,18 +863,45 @@ EOF;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->getProxyDumper()->isProxyCandidate($definition)) {
|
if (!$definition->isShared()) {
|
||||||
$factoryCode = $definition->isShared() ? ($asFile ? "\$this->load('%s', false)" : '$this->%s(false)') : '$this->factories[%2$s](false)';
|
$factory = sprintf('$this->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id));
|
||||||
$factoryCode = $this->getProxyDumper()->getProxyFactoryCode($definition, $id, sprintf($factoryCode, $methodName, $this->doExport($id)));
|
}
|
||||||
|
|
||||||
|
if ($isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition)) {
|
||||||
|
if (!$definition->isShared()) {
|
||||||
|
$code .= sprintf(' %s = %1$s ?? ', $factory);
|
||||||
|
|
||||||
|
if ($asFile) {
|
||||||
|
$code .= "function () {\n";
|
||||||
|
$code .= " return self::do(\$container);\n";
|
||||||
|
$code .= " };\n\n";
|
||||||
|
} else {
|
||||||
|
$code .= sprintf("\\Closure::fromCallable([\$this, '%s']);\n\n", $methodName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$factoryCode = $asFile ? 'self::do($container, false)' : sprintf('$this->%s(false)', $methodName);
|
||||||
|
$factoryCode = $this->getProxyDumper()->getProxyFactoryCode($definition, $id, $factoryCode);
|
||||||
$code .= $asFile ? preg_replace('/function \(([^)]*+)\) {/', 'function (\1) use ($container) {', $factoryCode) : $factoryCode;
|
$code .= $asFile ? preg_replace('/function \(([^)]*+)\) {/', 'function (\1) use ($container) {', $factoryCode) : $factoryCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
$code .= $this->addServiceInclude($id, $definition);
|
$c = $this->addServiceInclude($id, $definition);
|
||||||
|
|
||||||
|
if ('' !== $c && $isProxyCandidate && !$definition->isShared()) {
|
||||||
|
$c = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $c)));
|
||||||
|
$code .= " static \$include = true;\n\n";
|
||||||
|
$code .= " if (\$include) {\n";
|
||||||
|
$code .= $c;
|
||||||
|
$code .= " \$include = false;\n";
|
||||||
|
$code .= " }\n\n";
|
||||||
|
} else {
|
||||||
|
$code .= $c;
|
||||||
|
}
|
||||||
|
|
||||||
$c = $this->addInlineService($id, $definition);
|
$c = $this->addInlineService($id, $definition);
|
||||||
|
|
||||||
if (!$definition->isShared()) {
|
if (!$isProxyCandidate && !$definition->isShared()) {
|
||||||
$c = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $c)));
|
$c = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $c)));
|
||||||
$factory = sprintf('$this->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id));
|
|
||||||
$lazyloadInitialization = $definition->isLazy() ? '$lazyLoad = true' : '';
|
$lazyloadInitialization = $definition->isLazy() ? '$lazyLoad = true' : '';
|
||||||
|
|
||||||
$c = sprintf(" %s = function (%s) {\n%s };\n\n return %1\$s();\n", $factory, $lazyloadInitialization, $c);
|
$c = sprintf(" %s = function (%s) {\n%s };\n\n return %1\$s();\n", $factory, $lazyloadInitialization, $c);
|
||||||
|
@ -307,6 +307,7 @@ class PhpDumperTest extends TestCase
|
|||||||
->setLazy(true);
|
->setLazy(true);
|
||||||
$container->compile();
|
$container->compile();
|
||||||
$dumper = new PhpDumper($container);
|
$dumper = new PhpDumper($container);
|
||||||
|
$dumper->setProxyDumper(new \DummyProxyDumper());
|
||||||
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'inline_factories_parameter' => false, 'inline_class_loader_parameter' => false]), true);
|
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'inline_factories_parameter' => false, 'inline_class_loader_parameter' => false]), true);
|
||||||
|
|
||||||
if ('\\' === \DIRECTORY_SEPARATOR) {
|
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||||
|
@ -67,13 +67,11 @@ class ProjectServiceContainer extends Container
|
|||||||
*/
|
*/
|
||||||
protected function getFooService($lazyLoad = true)
|
protected function getFooService($lazyLoad = true)
|
||||||
{
|
{
|
||||||
|
$this->factories['service_container']['foo'] = $this->factories['service_container']['foo'] ?? \Closure::fromCallable([$this, 'getFooService']);
|
||||||
|
|
||||||
// lazy factory for stdClass
|
// lazy factory for stdClass
|
||||||
|
|
||||||
$this->factories['service_container']['foo'] = function ($lazyLoad = true) {
|
return new \stdClass();
|
||||||
return new \stdClass();
|
|
||||||
};
|
|
||||||
|
|
||||||
return $this->factories['service_container']['foo']();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,16 +28,34 @@ class getNonSharedFooService extends ProjectServiceContainer
|
|||||||
*/
|
*/
|
||||||
public static function do($container, $lazyLoad = true)
|
public static function do($container, $lazyLoad = true)
|
||||||
{
|
{
|
||||||
include_once $container->targetDir.''.'/Fixtures/includes/foo_lazy.php';
|
$container->factories['non_shared_foo'] = $container->factories['non_shared_foo'] ?? function () use ($container) {
|
||||||
|
return self::do($container);
|
||||||
$container->factories['non_shared_foo'] = function ($lazyLoad = true) use ($container) {
|
|
||||||
return new \Bar\FooLazyClass();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return $container->factories['non_shared_foo']();
|
// lazy factory for Bar\FooLazyClass
|
||||||
|
|
||||||
|
static $include = true;
|
||||||
|
|
||||||
|
if ($include) {
|
||||||
|
include_once $container->targetDir.''.'/Fixtures/includes/foo_lazy.php';
|
||||||
|
|
||||||
|
$include = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new \Bar\FooLazyClass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Container%s/proxy.php] => <?php
|
||||||
|
|
||||||
|
namespace Container%s;
|
||||||
|
|
||||||
|
// proxy code for Bar\FooLazyClass
|
||||||
|
|
||||||
|
if (!\class_exists('proxy', false)) {
|
||||||
|
\class_alias(__NAMESPACE__.'\\proxy', 'proxy', false);
|
||||||
|
}
|
||||||
|
|
||||||
[Container%s/ProjectServiceContainer.php] => <?php
|
[Container%s/ProjectServiceContainer.php] => <?php
|
||||||
|
|
||||||
namespace Container%s;
|
namespace Container%s;
|
||||||
@ -105,6 +123,13 @@ class ProjectServiceContainer extends Container
|
|||||||
|
|
||||||
return class_exists($class, false) ? $class::do($this, $lazyLoad) : $service;
|
return class_exists($class, false) ? $class::do($this, $lazyLoad) : $service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function createProxy($class, \Closure $factory)
|
||||||
|
{
|
||||||
|
class_exists($class, false) || require __DIR__.'/'.$class.'.php';
|
||||||
|
|
||||||
|
return $factory();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ProjectServiceContainer.preload.php] => <?php
|
[ProjectServiceContainer.preload.php] => <?php
|
||||||
@ -120,6 +145,7 @@ if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) {
|
|||||||
|
|
||||||
require dirname(__DIR__, %d).'%svendor/autoload.php';
|
require dirname(__DIR__, %d).'%svendor/autoload.php';
|
||||||
require __DIR__.'/Container%s/ProjectServiceContainer.php';
|
require __DIR__.'/Container%s/ProjectServiceContainer.php';
|
||||||
|
require __DIR__.'/Container%s/proxy.php';
|
||||||
require __DIR__.'/Container%s/getNonSharedFooService.php';
|
require __DIR__.'/Container%s/getNonSharedFooService.php';
|
||||||
|
|
||||||
$classes = [];
|
$classes = [];
|
||||||
|
Reference in New Issue
Block a user