diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index aa820c506994..9313256003e0 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -769,11 +769,40 @@ public function make($abstract, array $parameters = []) { $abstract = $this->getAlias($abstract); + $this->loadDeferredProviderIfNeeded($abstract); + + return parent::make($abstract, $parameters); + } + + /** + * Load deferred provider if $abstract is deferred service and instance was not loaded. + * + * @param string $abstract + */ + private function loadDeferredProviderIfNeeded($abstract) + { if ($this->isDeferredService($abstract) && ! isset($this->instances[$abstract])) { $this->loadDeferredProvider($abstract); } + } - return parent::make($abstract, $parameters); + /** + * Resolve the given type from the container. + * + * (Overriding Container::resolve) + * + * @param string $abstract + * @param array $parameters + * @param bool $raiseEvents + * @return mixed + */ + protected function resolve($abstract, $parameters = [], $raiseEvents = true) + { + $abstract = $this->getAlias($abstract); + + $this->loadDeferredProviderIfNeeded($abstract); + + return parent::resolve($abstract, $parameters, $raiseEvents); } /** diff --git a/tests/Foundation/FoundationApplicationTest.php b/tests/Foundation/FoundationApplicationTest.php index 9be9be52b31f..c3f1aa1450b3 100755 --- a/tests/Foundation/FoundationApplicationTest.php +++ b/tests/Foundation/FoundationApplicationTest.php @@ -172,6 +172,17 @@ public function testSingleProviderCanProvideMultipleDeferredServices() $this->assertSame('foobar', $app->make('bar')); } + public function testDeferredServiceIsLoadedWhenAccessingImplementationThroughInterface() + { + $app = new Application; + $app->setDeferredServices([ + SampleInterface::class => InterfaceToImplementationDeferredServiceProvider::class, + SampleImplementation::class => SampleImplementationDeferredServiceProvider::class, + ]); + $instance = $app->make(SampleInterface::class); + $this->assertEquals($instance->getPrimitive(), 'foo'); + } + public function testEnvironment() { $app = new Application; @@ -473,6 +484,44 @@ public function register() } } +interface SampleInterface +{ + public function getPrimitive(); +} + +class SampleImplementation implements SampleInterface +{ + private $primitive; + + public function __construct($primitive) + { + $this->primitive = $primitive; + } + + public function getPrimitive() + { + return $this->primitive; + } +} + +class InterfaceToImplementationDeferredServiceProvider extends ServiceProvider implements DeferrableProvider +{ + public function register() + { + $this->app->bind(SampleInterface::class, SampleImplementation::class); + } +} + +class SampleImplementationDeferredServiceProvider extends ServiceProvider implements DeferrableProvider +{ + public function register() + { + $this->app->when(SampleImplementation::class)->needs('$primitive')->give(function () { + return 'foo'; + }); + } +} + class ApplicationFactoryProviderStub extends ServiceProvider implements DeferrableProvider { public function register()