Skip to content

Commit 099fc45

Browse files
committed
fix: container resolution order when resolving class dependencies
1 parent 61adf1a commit 099fc45

File tree

2 files changed

+41
-10
lines changed

2 files changed

+41
-10
lines changed

src/Illuminate/Container/Container.php

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,22 +1108,32 @@ protected function resolvePrimitive(ReflectionParameter $parameter)
11081108
*/
11091109
protected function resolveClass(ReflectionParameter $parameter)
11101110
{
1111+
$className = Util::getParameterClassName($parameter);
1112+
1113+
// First, we check if the dependency has been explicitly bound in
1114+
// the container, and if so, we resolve it directly from there
1115+
// to respect explicit bindings over developer set defaults.
1116+
if ($this->bound($className)) {
1117+
return $this->make($className);
1118+
}
1119+
1120+
// If no binding exists, we check if any default value is
1121+
// available and return it. This avoids overriding any
1122+
// developer set defaults when constructing classes.
1123+
if ($parameter->isDefaultValueAvailable()) {
1124+
return $parameter->getDefaultValue();
1125+
}
1126+
11111127
try {
11121128
return $parameter->isVariadic()
11131129
? $this->resolveVariadicClass($parameter)
1114-
: $this->make(Util::getParameterClassName($parameter));
1130+
: $this->make($className);
11151131
}
11161132

1117-
// If we can not resolve the class instance, we will check to see if the value
1118-
// is optional, and if it is we will return the optional parameter value as
1119-
// the value of the dependency, similarly to how we do this with scalars.
1133+
// If we can not resolve the class instance, we will check to see if the
1134+
// value is variadic, and if it is we will return an empty array as the
1135+
// value of the dependency, similarly to how we do this with scalars.
11201136
catch (BindingResolutionException $e) {
1121-
if ($parameter->isDefaultValueAvailable()) {
1122-
array_pop($this->with);
1123-
1124-
return $parameter->getDefaultValue();
1125-
}
1126-
11271137
if ($parameter->isVariadic()) {
11281138
array_pop($this->with);
11291139

tests/Container/ContainerTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,18 @@ public function testResolutionOfDefaultParameters()
289289
$this->assertSame('taylor', $instance->default);
290290
}
291291

292+
public function testResolutionOfClassWithDefaultParameters()
293+
{
294+
$container = new Container;
295+
$instance = $container->make(ContainerClassWithDefaultValueStub::class);
296+
$this->assertInstanceOf(ContainerConcreteStub::class, $instance->noDefault);
297+
$this->assertSame(null, $instance->default);
298+
299+
$container->bind(ContainerConcreteStub::class, fn () => new ContainerConcreteStub);
300+
$instance = $container->make(ContainerClassWithDefaultValueStub::class);
301+
$this->assertInstanceOf(ContainerConcreteStub::class, $instance->default);
302+
}
303+
292304
public function testBound()
293305
{
294306
$container = new Container;
@@ -765,6 +777,15 @@ public function __construct(ContainerConcreteStub $stub, $default = 'taylor')
765777
}
766778
}
767779

780+
class ContainerClassWithDefaultValueStub
781+
{
782+
public function __construct(
783+
public ?ContainerConcreteStub $noDefault,
784+
public ?ContainerConcreteStub $default = null,
785+
) {
786+
}
787+
}
788+
768789
class ContainerMixedPrimitiveStub
769790
{
770791
public $first;

0 commit comments

Comments
 (0)