Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[DI] The generated code for lazy non-shared services doesn't work #38327

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
surikman opened this issue Sep 28, 2020 · 4 comments
Closed

[DI] The generated code for lazy non-shared services doesn't work #38327

surikman opened this issue Sep 28, 2020 · 4 comments

Comments

@surikman
Copy link
Contributor

surikman commented Sep 28, 2020

Symfony version(s) affected: >=5.1.3

Description
When a service is declared as lazy and non-shared, generated code uses $this->factories['service_name'](false); inside proxy without initialization of $this->factories['service_name'] before.

How to reproduce

class MyClass {}

$container = new ContainerBuilder();

$container->register('non_shared_foo', MyClass::class)->setShared(false)->setLazy(true)->setPublic(true);
$container->compile();

$dumper = new PhpDumper($container);
$dumper->setProxyDumper(new ProxyDumper());

print_r($dumper->dump(['as_files' => false]));

The generated getNonSharedFooService looks like this:

protected function getNonSharedFooService($lazyLoad = true)
{
    if ($lazyLoad) {
        return $this->createProxy('MyClass_c5258b3', function () {
            return \MyClass_c5258b3::staticProxyConstructor(function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {
                $wrappedInstance = $this->factories['non_shared_foo'](false);

                $proxy->setProxyInitializer(null);

                return true;
            });
        });
    }

    $this->factories['non_shared_foo'] = function ($lazyLoad = true) {
        return new \MyClass();
    };

    return $this->factories['non_shared_foo']();
}

Possible Solution
This bug comes from this commit - symfony/dependency-injection@37d0137 (#37435)
when I change back this

$factoryCode = $definition->isShared() ? ($asFile ? "\$this->load('%s', false)" : '$this->%s(false)') : '$this->factories[%2$s](false)';

to this

$factoryCode = $asFile ? "\$this->load('%s', false)" : '$this->%s(false)';

it works well.

@stof
Copy link
Member

stof commented Sep 28, 2020

/cc @nicolas-grekas

@fabpot fabpot closed this as completed Oct 1, 2020
fabpot added a commit that referenced this issue Oct 1, 2020
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
-------

e33a0b0 [DI] fix dumping non-shared lazy services
@vkurdin-aw
Copy link

@nicolas-grekas
Look like this is also reproducible on 4.4.21.
The reproduce-snippet from OP is generating correct code. But compiled code from real project is still affected.

services.yml:

    Acme\FooClass:
        public: true
        lazy: true
        shared: false

getFooClassService.php:

use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
// Returns the public 'Acme\FooClass' service.

if ($lazyLoad) {
    return $this->createProxy('FooClass_704b59e', function () {
        return \FooClass_704b59e::staticProxyConstructor(function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {
            $wrappedInstance = $this->factories['Acme\\FooClass'](false);

            $proxy->setProxyInitializer(null);

            return true;
        });
    });
}

include_once \dirname(__DIR__, 4).'/Acme/FooClass.php';

$this->factories['Acme\\FooClass'] = function ($lazyLoad = true) {
    return new \Acme\FooClass();
};

return $this->factories['Acme\\FooClass']();

@nicolas-grekas
Copy link
Member

@vkurdin-aw can you please open a new issue with a reproducer?

@vkurdin-aw
Copy link

@nicolas-grekas done #40642

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants