Skip to content

Commit

Permalink
[8.x] Container - detect circular dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmedash95 authored and taylorotwell committed Mar 11, 2021
1 parent 5d093e2 commit dd7274d
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/Illuminate/Container/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Illuminate\Contracts\Container;

use Exception;
use Psr\Container\ContainerExceptionInterface;

class CircularDependencyFoundException extends Exception implements ContainerExceptionInterface
{
//
}
26 changes: 26 additions & 0 deletions tests/Container/ContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Container\Container;
use Illuminate\Container\EntryNotFoundException;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Contracts\Container\CircularDependencyFoundException;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerExceptionInterface;
use stdClass;
Expand Down Expand Up @@ -562,6 +563,31 @@ public function testContainerCanResolveClasses()

$this->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
Expand Down

0 comments on commit dd7274d

Please sign in to comment.