From dd7274d23a9ee58cc1abdf7107403169a3994b68 Mon Sep 17 00:00:00 2001 From: Ahmed Ashraf Date: Wed, 10 Mar 2021 18:03:35 +0100 Subject: [PATCH] [8.x] Container - detect circular dependencies --- src/Illuminate/Container/Container.php | 8 +++++- .../CircularDependencyFoundException.php | 11 ++++++++ tests/Container/ContainerTest.php | 26 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/Illuminate/Contracts/Container/CircularDependencyFoundException.php diff --git a/src/Illuminate/Container/Container.php b/src/Illuminate/Container/Container.php index 2cfa72f51bb7..abf94c99861c 100755 --- a/src/Illuminate/Container/Container.php +++ b/src/Illuminate/Container/Container.php @@ -6,6 +6,7 @@ use Closure; use Exception; use Illuminate\Contracts\Container\BindingResolutionException; +use Illuminate\Contracts\Container\CircularDependencyFoundException; use Illuminate\Contracts\Container\Container as ContainerContract; use LogicException; use ReflectionClass; @@ -659,7 +660,7 @@ public function get($id) try { return $this->resolve($id); } catch (Exception $e) { - if ($this->has($id)) { + if ($this->has($id) || $e instanceof CircularDependencyFoundException) { throw $e; } @@ -839,6 +840,11 @@ public function build($concrete) return $this->notInstantiable($concrete); } + // Check for circular dependencies + if(in_array($concrete, $this->buildStack)) { + throw new CircularDependencyFoundException("Circular dependency while initiating [{$concrete}]"); + } + $this->buildStack[] = $concrete; $constructor = $reflector->getConstructor(); diff --git a/src/Illuminate/Contracts/Container/CircularDependencyFoundException.php b/src/Illuminate/Contracts/Container/CircularDependencyFoundException.php new file mode 100644 index 000000000000..d6d0398e93ef --- /dev/null +++ b/src/Illuminate/Contracts/Container/CircularDependencyFoundException.php @@ -0,0 +1,11 @@ +assertInstanceOf(ContainerConcreteStub::class, $class); } + + public function testContainerCanCatchCircularDependency() { + $this->expectException(CircularDependencyFoundException::class); + + $container = new Container; + $container->get(CircularAStub::class); + } +} + +class CircularAStub { + public function __construct(CircularBStub $b) { + + } +} + +class CircularBStub { + public function __construct(CircularCStub $c) { + + } +} + +class CircularCStub { + public function __construct(CircularAStub $a) { + + } } class ContainerConcreteStub