framework: Container's extend() does not work with deferred services
I was about to go on a rampage writing a blog post loudly exclaiming that every service provider out there is doing it wrong.
Until I realized they can’t do better.
My thesis: when a service provider adds an additional driver for, say, the authentication manager, it should not, just to extend it, instantiate the driver. Instead, the extension should only be resolved once the manager is actually requested from the container. The extend()
method exists exactly for such a reason.
So, for my FluxBB authentication adapter, code currently looks like this:
$this->app['auth']->extend('fluxbb1', function($app)
{
$connector = $app['fluxbb1.db.connector'];
$provider = new UserProvider($connector->connection());
return new Guard($provider, $app['fluxbb1.cookie.storage']);
});
It really should work like this, though:
$this->app->extend('auth', function($auth, $app)
{
$auth->extend('fluxbb1', function($app)
{
$connector = $app['fluxbb1.db.connector'];
$provider = new UserProvider($connector->connection());
return new Guard($provider, $app['fluxbb1.cookie.storage']);
});
return $auth;
});
A tad more code, but it avoids instantiating unneeded container objects.
The actual problem: when a service provider is deferred (which is a good thing), you can not call extend()
on any bindings that are registered in that provider. Instead, you get an exception saying that nothing is bound for the given key - “auth” in this case.
About this issue
- Original URL
- State: closed
- Created 11 years ago
- Comments: 15 (15 by maintainers)
That might actually be the best way.
I just experimented around and found that extending the
extend()
method inIlluminate\Foundation\Application
like this would work, too:The downside would probably be that the deferred provider would be loaded, even if it’s not needed, which is somewhat counter-productive, especially as this issue is about only instantiating when needed. On the other hand, the current behaviour is more-or-less a bug.