Skip to content

Commit

Permalink
fix: container resolution order when resolving class dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
calebdw committed Nov 15, 2024
1 parent 4b1f01f commit c5331cd
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 10 deletions.
30 changes: 20 additions & 10 deletions src/Illuminate/Container/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -1108,22 +1108,32 @@ protected function resolvePrimitive(ReflectionParameter $parameter)
*/
protected function resolveClass(ReflectionParameter $parameter)
{
$className = Util::getParameterClassName($parameter);

// First, we check if the dependency has been explicitly bound in
// the container, and if so, we resolve it directly from there
// to respect explicit bindings over developer set defaults.
if ($this->bound($className)) {
return $this->make($className);
}

// If no binding exists, we check if any default value is
// available and return it. This avoids overriding any
// developer set defaults when constructing classes.
if ($parameter->isDefaultValueAvailable()) {
return $parameter->getDefaultValue();
}

try {
return $parameter->isVariadic()
? $this->resolveVariadicClass($parameter)
: $this->make(Util::getParameterClassName($parameter));
: $this->make($className);
}

// If we can not resolve the class instance, we will check to see if the value
// is optional, and if it is we will return the optional parameter value as
// the value of the dependency, similarly to how we do this with scalars.
// If we can not resolve the class instance, we will check to see if the
// value is variadic, and if it is we will return an empty array as the
// value of the dependency, similarly to how we do this with scalars.
catch (BindingResolutionException $e) {
if ($parameter->isDefaultValueAvailable()) {
array_pop($this->with);

return $parameter->getDefaultValue();
}

if ($parameter->isVariadic()) {
array_pop($this->with);

Expand Down
21 changes: 21 additions & 0 deletions tests/Container/ContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,18 @@ public function testResolutionOfDefaultParameters()
$this->assertSame('taylor', $instance->default);
}

public function testResolutionOfClassWithDefaultParameters()
{
$container = new Container;
$instance = $container->make(ContainerClassWithDefaultValueStub::class);
$this->assertInstanceOf(ContainerConcreteStub::class, $instance->noDefault);
$this->assertSame(null, $instance->default);

$container->bind(ContainerConcreteStub::class, fn () => new ContainerConcreteStub);
$instance = $container->make(ContainerClassWithDefaultValueStub::class);
$this->assertInstanceOf(ContainerConcreteStub::class, $instance->default);
}

public function testBound()
{
$container = new Container;
Expand Down Expand Up @@ -765,6 +777,15 @@ public function __construct(ContainerConcreteStub $stub, $default = 'taylor')
}
}

class ContainerClassWithDefaultValueStub
{
public function __construct(
public ?ContainerConcreteStub $noDefault,
public ?ContainerConcreteStub $default = null,
) {
}
}

class ContainerMixedPrimitiveStub
{
public $first;
Expand Down

0 comments on commit c5331cd

Please sign in to comment.