diff --git a/src/Definition/Definition.php b/src/Definition/Definition.php index 8ff440d..2972d70 100644 --- a/src/Definition/Definition.php +++ b/src/Definition/Definition.php @@ -12,6 +12,7 @@ }; use League\Container\ContainerAwareTrait; use League\Container\Exception\ContainerException; +use League\Container\Exception\NotFoundException; use Psr\Container\ContainerInterface; use ReflectionClass; @@ -55,6 +56,11 @@ class Definition implements ArgumentResolverInterface, DefinitionInterface */ protected $resolved; + /** + * @var bool + */ + protected $isAlreadySearched = false; + /** * @param string $id * @param mixed|null $concrete @@ -185,9 +191,17 @@ public function resolveNew() $container = null; } + // stop recursive resolving + if ($this->isAlreadySearched) { + throw new NotFoundException( + sprintf('Alias or class "%s" did not found.', $concrete) + ); + } + // if we still have a string, try to pull it from the container // this allows for `alias -> alias -> ... -> concrete if (is_string($concrete) && $container instanceof ContainerInterface && $container->has($concrete)) { + $this->isAlreadySearched = true; $concrete = $container->get($concrete); } diff --git a/tests/ContainerTest.php b/tests/ContainerTest.php index 4df3680..f8054ab 100644 --- a/tests/ContainerTest.php +++ b/tests/ContainerTest.php @@ -221,4 +221,15 @@ public function testContainerAwareCannotBeUsedWithoutImplementingInterface(): vo $container = $this->getMockBuilder(Container::class)->getMock(); $class->setContainer($container); } + + public function testNonExistentClassCausesException(): void + { + $container = new Container(); + $container->add(NonExistent::class); + + self::assertTrue($container->has(NonExistent::class)); + + $this->expectException(NotFoundException::class); + $container->get(NonExistent::class); + } }