Skip to content

[DependencyInjection] allows references to be declared as "lazy" #6140

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 1 commit into from

Conversation

schmittjoh
Copy link
Contributor

I had written this patch during sflive Berlin. It allows to store additional metadata in references. It contains no code to leverage that additional metadata though.

In contrast to regular references, a lazy reference is not guaranteed to be fully initialized upon injection, but may instead be lazy initialized when it is first accessed by the consuming service.

Code that uses the lazy attribute could also reside outside of the core repository as it might contain additional dependencies which we probably do not want in the core component.

In contrast to regular references, a lazy references is not guaranteed to be fully
initialized upon injection, but may instead be lazy initialized when it is first
accessed by the consuming service.

Lazy makes no implementation restrictions on how those referenced services are
to be constructed but leave this up to a concrete implementor.
@@ -25,6 +25,7 @@
* XmlFileLoader loads XML files service definitions.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I was going to change the file, and saw that I had not yet added my name :) Anyway, I have made many small feature additions in this file that should warrant the tag.

If possible, I'd like to first talk about the general idea of this patch though. If we agree on that, we can also talk about when @author tags are justified, and whether this one (or others) need to be removed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i was just curious, sorry for that

@asm89
Copy link
Contributor

asm89 commented Nov 28, 2012

Maybe the GraphvizDumper can also show something on the edges if a service is "lazy"?

@Ocramius
Copy link
Contributor

@schmittjoh do you think tests for lazy services should reside in core?

@stof
Copy link
Member

stof commented Nov 28, 2012

@schmittjoh is it meant to be used for #5012 or is it totally unrelated ?

@schmittjoh
Copy link
Contributor Author

@stof, that is what it would be used for.

@andrerom
Copy link
Contributor

andrerom commented Dec 4, 2012

This seems to be useful for #6102 as well.

Regarding the patch; seems strict was partly there from before, but not covered by tests. Elsewhere, or should it be added?

@schmittjoh
Copy link
Contributor Author

Yes, there were a few bugs I noticed when adding lazy.

Regarding #6102, you might want to look at http://jmsyst.com/bundles/JMSDiExtraBundle/master/lazy_service_collections. You already should have that capability if you are using the Symfony Standard Edition.

@fabpot
Copy link
Member

fabpot commented Apr 21, 2013

Closing as the discussion should now happen on #7527

@fabpot fabpot closed this Apr 21, 2013
@Ocramius Ocramius mentioned this pull request May 1, 2013
fabpot added a commit that referenced this pull request May 6, 2013
This PR was squashed before being merged into the master branch (closes #7890).

Discussion
----------

ProxyManager Bridge

As of @beberlei's suggestion, I re-implemented #7527 as a new bridge to avoid possible hidden dependencies.

Everything is like #7527 except that the new namespace (and possibly package/subtree split) `Symfony\Bridge\ProxyManager` is introduced

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #6140 (supersedes) #5012 #6102 (maybe) #7527 (supersedes)
| License       | MIT (attached code) - BSD-3-Clause (transitive dependency)
| Doc PR        | Please pester me to death so I do it

This PR introduces lazy services along the lines of zendframework/zendframework#4146

It introduces an **OPTIONAL** dependency to [ProxyManager](https://github.com/Ocramius/ProxyManager) and transitively to [`"zendframework/zend-code": "2.*"`](https://github.com/zendframework/zf2/tree/master/library/Zend/Code).

## Lazy services: why? A comprehensive example

For those who don't know what this is about, here's an example.

Assuming you have a service class like following:

```php
class MySuperSlowClass
{
    public function __construct()
    {
        // inject large object graph or do heavy computation
        sleep(10);
    }

    public function doFoo()
    {
        echo 'Foo!';
    }
}
```

The DIC will hang for 10 seconds when calling:

```php
$container->get('my_super_slow_class');
```

With this PR, this can be avoided, and the following call will return a proxy immediately.

```php
$container->getDefinitions('my_super_slow_class')->setLazy(true);
$service = $container->get('my_super_slow_class');
```

The 10 seconds wait time will be delayed until the object is actually used:

```php
$service->doFoo(); // wait 10 seconds, then 'Foo!'
```

A more extensive description of the functionality can be found [here](https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md).

## When do we need it?

Lazy services can be used to optimize the dependency graph in cases like:

 * Webservice endpoints
 * Db connections
 * Objects that cause I/O in general
 * Large dependency graphs that are not always used

This could also help in reducing excessive service location usage as I've explained [here](http://ocramius.github.com/blog/zf2-and-symfony-service-proxies-with-doctrine-proxies/).

## Implementation quirks of this PR

There's a couple of quirks in the implementation:

 * `Symfony\Component\DependencyInjection\CompilerBuilder#createService` is now public because of the limitations of PHP 5.3
 * `Symfony\Component\DependencyInjection\Dumper\PhpDumper` now with extra mess!
 * The proxies are dumped at the end of compiled containers, therefore the container class is not PSR compliant anymore

Commits
-------

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

Successfully merging this pull request may close these issues.

7 participants