From c0cfc1334b5dc1ce7c29cbdce3a493476d3098a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Przyby=C5=82ek?= Date: Thu, 27 Feb 2020 20:06:10 +0100 Subject: [PATCH 1/6] Add test that failes to load deffered provider of implementation while accessing class through interface --- .../Foundation/FoundationApplicationTest.php | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) 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() From 8943aad90ba81c8a088b7e7c6cdd63ee41f6e01b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Przyby=C5=82ek?= Date: Thu, 27 Feb 2020 20:07:12 +0100 Subject: [PATCH 2/6] Call make instead of resolve to load deffered providers This commit brings back behaviour from Laravel 5.7 when you could use deferred provides to bind an interface to implementation even when implementation had its own deferred provider. Changing `resolve` method to `make` results in calling `Illuminate\Foundation\Application::make` method which loads deferred providers. Calling `resolve` method calls `Illuminate\Container\Container::resolve` which does not load deferred providers. --- src/Illuminate/Container/Container.php | 7 ++++--- src/Illuminate/Contracts/Container/Container.php | 3 ++- src/Illuminate/Foundation/Application.php | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Illuminate/Container/Container.php b/src/Illuminate/Container/Container.php index b595b5c9230c..f767ca0af121 100755 --- a/src/Illuminate/Container/Container.php +++ b/src/Illuminate/Container/Container.php @@ -261,7 +261,7 @@ protected function getClosure($abstract, $concrete) return $container->build($concrete); } - return $container->resolve( + return $container->make( $concrete, $parameters, $raiseEvents = false ); }; @@ -620,13 +620,14 @@ public function makeWith($abstract, array $parameters = []) * * @param string $abstract * @param array $parameters + * @param bool $raiseEvents * @return mixed * * @throws \Illuminate\Contracts\Container\BindingResolutionException */ - public function make($abstract, array $parameters = []) + public function make($abstract, array $parameters = [], $raiseEvents = true) { - return $this->resolve($abstract, $parameters); + return $this->resolve($abstract, $parameters, $raiseEvents); } /** diff --git a/src/Illuminate/Contracts/Container/Container.php b/src/Illuminate/Contracts/Container/Container.php index 1b8bb6407934..1749b8ea7001 100644 --- a/src/Illuminate/Contracts/Container/Container.php +++ b/src/Illuminate/Contracts/Container/Container.php @@ -139,11 +139,12 @@ public function flush(); * * @param string $abstract * @param array $parameters + * @param bool $raiseEvents * @return mixed * * @throws \Illuminate\Contracts\Container\BindingResolutionException */ - public function make($abstract, array $parameters = []); + public function make($abstract, array $parameters = [], $raiseEvents = true); /** * Call the given Closure / class@method and inject its dependencies. diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index aa820c506994..086885b8bbb2 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -763,9 +763,10 @@ public function registerDeferredProvider($provider, $service = null) * * @param string $abstract * @param array $parameters + * @param bool $raiseEvents * @return mixed */ - public function make($abstract, array $parameters = []) + public function make($abstract, array $parameters = [], $raiseEvents = true) { $abstract = $this->getAlias($abstract); @@ -773,7 +774,7 @@ public function make($abstract, array $parameters = []) $this->loadDeferredProvider($abstract); } - return parent::make($abstract, $parameters); + return parent::make($abstract, $parameters, $raiseEvents); } /** From 00bc2c048bad6cb7061baef75e529d0a7ef1fb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Przyby=C5=82ek?= Date: Thu, 27 Feb 2020 20:49:00 +0100 Subject: [PATCH 3/6] Revert "Call make instead of resolve to load deffered providers" This reverts commit 8943aad90ba81c8a088b7e7c6cdd63ee41f6e01b. --- src/Illuminate/Container/Container.php | 7 +++---- src/Illuminate/Contracts/Container/Container.php | 3 +-- src/Illuminate/Foundation/Application.php | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Illuminate/Container/Container.php b/src/Illuminate/Container/Container.php index f767ca0af121..b595b5c9230c 100755 --- a/src/Illuminate/Container/Container.php +++ b/src/Illuminate/Container/Container.php @@ -261,7 +261,7 @@ protected function getClosure($abstract, $concrete) return $container->build($concrete); } - return $container->make( + return $container->resolve( $concrete, $parameters, $raiseEvents = false ); }; @@ -620,14 +620,13 @@ public function makeWith($abstract, array $parameters = []) * * @param string $abstract * @param array $parameters - * @param bool $raiseEvents * @return mixed * * @throws \Illuminate\Contracts\Container\BindingResolutionException */ - public function make($abstract, array $parameters = [], $raiseEvents = true) + public function make($abstract, array $parameters = []) { - return $this->resolve($abstract, $parameters, $raiseEvents); + return $this->resolve($abstract, $parameters); } /** diff --git a/src/Illuminate/Contracts/Container/Container.php b/src/Illuminate/Contracts/Container/Container.php index 1749b8ea7001..1b8bb6407934 100644 --- a/src/Illuminate/Contracts/Container/Container.php +++ b/src/Illuminate/Contracts/Container/Container.php @@ -139,12 +139,11 @@ public function flush(); * * @param string $abstract * @param array $parameters - * @param bool $raiseEvents * @return mixed * * @throws \Illuminate\Contracts\Container\BindingResolutionException */ - public function make($abstract, array $parameters = [], $raiseEvents = true); + public function make($abstract, array $parameters = []); /** * Call the given Closure / class@method and inject its dependencies. diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 086885b8bbb2..aa820c506994 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -763,10 +763,9 @@ public function registerDeferredProvider($provider, $service = null) * * @param string $abstract * @param array $parameters - * @param bool $raiseEvents * @return mixed */ - public function make($abstract, array $parameters = [], $raiseEvents = true) + public function make($abstract, array $parameters = []) { $abstract = $this->getAlias($abstract); @@ -774,7 +773,7 @@ public function make($abstract, array $parameters = [], $raiseEvents = true) $this->loadDeferredProvider($abstract); } - return parent::make($abstract, $parameters, $raiseEvents); + return parent::make($abstract, $parameters); } /** From 746f2e9840900474172665fa4d73c7654d379b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Przyby=C5=82ek?= Date: Thu, 27 Feb 2020 21:12:44 +0100 Subject: [PATCH 4/6] Create resolve method which loads deferred providers if needed It allows resolving object by interface when using separate deferred providers for interface and implementation. --- src/Illuminate/Foundation/Application.php | 31 ++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index aa820c506994..f537af2ef78f 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 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); } /** From 86a64fb575d255e5c8288ebcddd62f506e0a4a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Przyby=C5=82ek?= Date: Thu, 27 Feb 2020 21:14:54 +0100 Subject: [PATCH 5/6] Fix styling for phpdoc --- src/Illuminate/Foundation/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index f537af2ef78f..2ee6e833c39a 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -775,7 +775,7 @@ public function make($abstract, array $parameters = []) } /** - * Load deferred provider if $abstract is deferred and instance was not loaded + * Load deferred provider if $abstract is deferred and instance was not loaded. * * @param string $abstract */ From 1b6b99a8e5405b1ed876b50c89cc7e3ed7d6d958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Przyby=C5=82ek?= Date: Thu, 27 Feb 2020 22:05:07 +0100 Subject: [PATCH 6/6] Fix phpdoc --- src/Illuminate/Foundation/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 2ee6e833c39a..9313256003e0 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -775,7 +775,7 @@ public function make($abstract, array $parameters = []) } /** - * Load deferred provider if $abstract is deferred and instance was not loaded. + * Load deferred provider if $abstract is deferred service and instance was not loaded. * * @param string $abstract */