diff --git a/src/Core/src/Internal/Proxy/Resolver.php b/src/Core/src/Internal/Proxy/Resolver.php index 01925890c..98af51d18 100644 --- a/src/Core/src/Internal/Proxy/Resolver.php +++ b/src/Core/src/Internal/Proxy/Resolver.php @@ -39,20 +39,25 @@ public static function resolve( ); } + if (!Proxy::isProxy($result)) { + return $result; + } + /** * If we got a Proxy again, that we should retry with the new context * to try to get the instance from the Proxy Fallback Factory. * If there is no the Proxy Fallback Factory, {@see RecursiveProxyException} will be thrown. */ - if (Proxy::isProxy($result)) { - try { - return $c->get($alias, new RetryContext($context)); - } catch (RecursiveProxyException $e) { - throw new RecursiveProxyException($e->alias, $e->bindingScope, self::getScope($c)); - } + try { + $result = $c->get($alias, new RetryContext($context)); + } catch (RecursiveProxyException $e) { + throw new RecursiveProxyException($e->alias, $e->bindingScope, self::getScope($c)); } - return $result; + // If Container returned a Proxy after the retry, then we have a recursion. + return Proxy::isProxy($result) + ? throw new RecursiveProxyException($alias, null, self::getScope($c)) + : $result; } /** diff --git a/src/Core/tests/Scope/ProxyTest.php b/src/Core/tests/Scope/ProxyTest.php index 7a4504e41..7c94f1c2d 100644 --- a/src/Core/tests/Scope/ProxyTest.php +++ b/src/Core/tests/Scope/ProxyTest.php @@ -302,7 +302,7 @@ public function __toString(): string /** * Proxy gets a proxy of the same type. */ - public function testRecursiveProxy(): void + public function testRecursiveProxyNotSingleton(): void { $root = new Container(); $root->bind(UserInterface::class, new ProxyConfig(UserInterface::class)); @@ -322,6 +322,28 @@ public function testRecursiveProxy(): void ); } + /** + * Proxy gets a proxy of the same type as a singleton. + */ + public function testRecursiveProxySingleton(): void + { + $root = new Container(); + $root->bind(UserInterface::class, new ProxyConfig(UserInterface::class, singleton: true)); + + $this->expectException(RecursiveProxyException::class); + $this->expectExceptionMessage( + <<runScope( + new Scope(), + fn(#[Proxy] UserInterface $user) => $user->getName(), + ); + } + /** * The {@see ContainerScope::runScope} ignores Container Proxy to avoid recursion. */