-
Notifications
You must be signed in to change notification settings - Fork 28
[Proposal] Lazy loading services when using dependency injection #1436
Comments
Any progress on implementing such a feature so far? |
I have not yet even started, not sure if it can be as separate package |
I think we would need really good benchmarks on how much of a difference this even makes. I think it would be negligible on a standard web app. Laravel already allows method injection at the controller level with the container. |
So I need to implement it and then benchmark it, is that what you mean?
yes, but that not exactly what I what since I want it in my own code that is kind of frameworkless (I mean simple POPOs).
the other way to do it is separate the Application and Container and then decorate the Application instance, but, as I think it's a lot of work to do, but this way it don't needs to be in the core |
I kinda think you're premature optimizing here a bit. |
@taylorotwell |
@vladyslavstartsev a simple workaround to resolve circular dependencies is to introduce a service factory, e.g.: <?php
namespace Practice\Tests\Unit;
use Closure;
use Illuminate\Container\Container;
class Foo1
{
private Bar1 $bar;
public function __construct(Bar1 $bar)
{
$this->bar = $bar;
}
public function hello()
{
}
}
class Bar1
{
private Foo1 $foo;
public function __construct(Foo1 $foo)
{
$this->foo = $foo;
}
public function world()
{
$this->foo->hello();
}
}
class Foo2
{
private Bar2 $bar;
public function __construct(Bar2 $bar)
{
$this->bar = $bar;
}
public function hello()
{
}
}
class Bar2
{
private Closure $fooFactory;
private Foo2 $foo;
public function __construct(Closure $fooFactory)
{
$this->fooFactory = $fooFactory;
}
public function world()
{
$this->foo()->hello();
}
private function foo(): Foo2
{
if (!isset($this->foo)) {
$this->foo = ($this->fooFactory)();
}
return $this->foo;
}
}
class CircularTest extends TestCase
{
public function testCircularFails()
{
$container = new Container();
$this->expectExceptionMessageMatches("/Maximum function nesting level of '\\d+' reached, aborting!/");
$container->get(Bar1::class)->world();
}
public function testFactorySucceeds()
{
$container = new Container();
$container->bind(Bar2::class, fn() => new Bar2(fn() => $container->get(Foo2::class)));
$container->get(Bar2::class)->world();
self::assertTrue(true);
}
} |
The why do we need it can be found here (tl;dr to not (fully) construct objects with dependency injection container when we don't use them, to defer their resolve to the moment when we will need them)
The idea is to implement something that will be similar to
The zend version and symfony uses the https://github.com/Ocramius/ProxyManager to achieve the goal
Some of the ideas of how to implement it in laravel you can see here (they are kinda old, but still )
How it was implemented in symfony and zend (the PRs)
The text was updated successfully, but these errors were encountered: