Skip to content

Commit dd7274d

Browse files
ahmedash95taylorotwell
authored andcommitted
[8.x] Container - detect circular dependencies
1 parent 5d093e2 commit dd7274d

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

src/Illuminate/Container/Container.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Closure;
77
use Exception;
88
use Illuminate\Contracts\Container\BindingResolutionException;
9+
use Illuminate\Contracts\Container\CircularDependencyFoundException;
910
use Illuminate\Contracts\Container\Container as ContainerContract;
1011
use LogicException;
1112
use ReflectionClass;
@@ -659,7 +660,7 @@ public function get($id)
659660
try {
660661
return $this->resolve($id);
661662
} catch (Exception $e) {
662-
if ($this->has($id)) {
663+
if ($this->has($id) || $e instanceof CircularDependencyFoundException) {
663664
throw $e;
664665
}
665666

@@ -839,6 +840,11 @@ public function build($concrete)
839840
return $this->notInstantiable($concrete);
840841
}
841842

843+
// Check for circular dependencies
844+
if(in_array($concrete, $this->buildStack)) {
845+
throw new CircularDependencyFoundException("Circular dependency while initiating [{$concrete}]");
846+
}
847+
842848
$this->buildStack[] = $concrete;
843849

844850
$constructor = $reflector->getConstructor();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Illuminate\Contracts\Container;
4+
5+
use Exception;
6+
use Psr\Container\ContainerExceptionInterface;
7+
8+
class CircularDependencyFoundException extends Exception implements ContainerExceptionInterface
9+
{
10+
//
11+
}

tests/Container/ContainerTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Container\Container;
66
use Illuminate\Container\EntryNotFoundException;
77
use Illuminate\Contracts\Container\BindingResolutionException;
8+
use Illuminate\Contracts\Container\CircularDependencyFoundException;
89
use PHPUnit\Framework\TestCase;
910
use Psr\Container\ContainerExceptionInterface;
1011
use stdClass;
@@ -562,6 +563,31 @@ public function testContainerCanResolveClasses()
562563

563564
$this->assertInstanceOf(ContainerConcreteStub::class, $class);
564565
}
566+
567+
public function testContainerCanCatchCircularDependency() {
568+
$this->expectException(CircularDependencyFoundException::class);
569+
570+
$container = new Container;
571+
$container->get(CircularAStub::class);
572+
}
573+
}
574+
575+
class CircularAStub {
576+
public function __construct(CircularBStub $b) {
577+
578+
}
579+
}
580+
581+
class CircularBStub {
582+
public function __construct(CircularCStub $c) {
583+
584+
}
585+
}
586+
587+
class CircularCStub {
588+
public function __construct(CircularAStub $a) {
589+
590+
}
565591
}
566592

567593
class ContainerConcreteStub

0 commit comments

Comments
 (0)