Closed
Description
Q | A |
---|---|
Bug report? | yes |
Feature request? | no |
BC Break report? | no |
RFC? | no |
Symfony version | 3.3.6 (maybe prev too) |
Given:
- Not existing class (in out case - cache adapter, which not exist on local dev env)
- Lazy service for this class
- Lazy aggregate service, having previous one as arguments
Code sample:
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\Reference;
final class UnknownLazyClassTest extends TestCase
{
public function testUnknownClassIsNotDestructed()
{
$builder = new ContainerBuilder();
$builder
->register('unknown_class', 'UnknownClass')
->setLazy(true)
->setArguments([1, 2, 3]);
$builder
->register('aggregate_service', Aggregate::class)
->setLazy(true)
->setProperty('dependency', new Reference('unknown_class'));
$builder->setProxyInstantiator(new RuntimeInstantiator());
$builder->compile();
// Ensure kernel can be dumped
$dumper = new PhpDumper($builder);
$dumper->setProxyDumper(new ProxyDumper());
//$dumper->dump();
$file = __DIR__ . '/../build/TestContainer.php';
$content = $dumper->dump(['class' => 'TestContainer']);
file_put_contents($file, $content);
require_once $file;
$container = new \TestContainer();
$container->get('aggregate_service');
$container->reset();
}
}
class Aggregate
{
public $dependency;
public function __destruct()
{
$this->dependency = null;
}
}
Expected behavior: no errors, since unknown class is lazy class was not instantiated
Actual behavior:
Class 'UnknownClass' not found
Container sample(can be generated from code snippet)
https://gist.github.com/scaytrase/602330145d08576427a2647ce0199c19
Stacktrace:
Class 'UnknownClass' not found
C:\Work\Projects\bankiru\issues\memcached-destruct\build\TestContainer.php:98
C:\Work\Projects\bankiru\issues\memcached-destruct\vendor\symfony\symfony\src\Symfony\Component\DependencyInjection\Container.php:335
C:\Work\Projects\bankiru\issues\memcached-destruct\build\TestContainer.php:86
C:\Work\Projects\bankiru\issues\memcached-destruct\build\TestContainer.php:75
C:\Work\Projects\bankiru\issues\memcached-destruct\build\TestContainer.php:127
C:\Work\Projects\bankiru\issues\memcached-destruct\build\TestContainer.php:127
C:\Work\Projects\bankiru\issues\memcached-destruct\vendor\symfony\symfony\src\Symfony\Component\DependencyInjection\Container.php:375
C:\Work\Projects\bankiru\issues\memcached-destruct\Tests\UnknownLazyClassTest.php:45
Stack trace contains destruct call method
/**
* {@inheritDoc}
*/
public function __destruct()
{
$this->initializer59881840d96a1613317297 && $this->initializer59881840d96a1613317297->__invoke($this->valueHolder59881840d9680583445445, $this, '__destruct', array(), $this->initializer59881840d96a1613317297);
return $this->valueHolder59881840d9680583445445->__destruct();
}
The problem is that calling __destruct
on non initialized service requires to initialize it first, which leads no unnecessary initialization and instantiation (for me for non-existent class, which is not really needed in dev)