Skip to content

Commit

Permalink
fix: allows injection using multiple interfaces with the same concret…
Browse files Browse the repository at this point in the history
…e implementation
  • Loading branch information
jamiethorpe committed Oct 23, 2024
1 parent 4b5ce19 commit 440ffeb
Showing 1 changed file with 27 additions and 16 deletions.
43 changes: 27 additions & 16 deletions src/Illuminate/Routing/ResolvesRouteDependencies.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,30 @@ public function resolveMethodDependencies(array $parameters, ReflectionFunctionA

$skippableValue = new stdClass;

$resolvedInterfaces = [];

foreach ($reflector->getParameters() as $key => $parameter) {
$instance = $this->transformDependency($parameter, $parameters, $skippableValue);
$className = Reflector::getParameterClassName($parameter);

// If the parameter has a type-hinted class, we will check to see if it is already in
// the list of parameters. If it is we will just skip it as it is probably a model
// binding and we do not want to mess with those; otherwise, we resolve it here.
if ($className && (! $this->alreadyInParameters($className, $parameters) || ! $this->alreadyInResolvedInterfaces($className, $resolvedInterfaces))) {
$instance = $this->transformDependency($parameter, $className);

if (interface_exists($className) && !class_exists($className) && $instance !== $skippableValue) {
$resolvedInterfaces[] = $className;
}
} else {
$instance = $skippableValue;
}

if ($instance !== $skippableValue) {
$instanceCount++;

$this->spliceIntoParameters($parameters, $key, $instance);
} elseif (! isset($values[$key - $instanceCount]) &&
$parameter->isDefaultValueAvailable()) {
$parameter->isDefaultValueAvailable()) {
$this->spliceIntoParameters($parameters, $key, $parameter->getDefaultValue());
}

Expand All @@ -73,26 +88,17 @@ public function resolveMethodDependencies(array $parameters, ReflectionFunctionA
* @param object $skippableValue
* @return mixed
*/
protected function transformDependency(ReflectionParameter $parameter, $parameters, $skippableValue)
protected function transformDependency(ReflectionParameter $parameter, $className)
{
$className = Reflector::getParameterClassName($parameter);

if ($attribute = Util::getContextualAttributeFromDependency($parameter)) {
return $this->container->resolveFromAttribute($attribute);
}

// If the parameter has a type-hinted class, we will check to see if it is already in
// the list of parameters. If it is we will just skip it as it is probably a model
// binding and we do not want to mess with those; otherwise, we resolve it here.
if ($className && ! $this->alreadyInParameters($className, $parameters)) {
$isEnum = (new ReflectionClass($className))->isEnum();

return $parameter->isDefaultValueAvailable()
? ($isEnum ? $parameter->getDefaultValue() : null)
: $this->container->make($className);
}
$isEnum = (new ReflectionClass($className))->isEnum();

return $skippableValue;
return $parameter->isDefaultValueAvailable()
? ($isEnum ? $parameter->getDefaultValue() : null)
: $this->container->make($className);
}

/**
Expand All @@ -107,6 +113,11 @@ protected function alreadyInParameters($class, array $parameters)
return ! is_null(Arr::first($parameters, fn ($value) => $value instanceof $class));
}

protected function alreadyInResolvedInterfaces($class, array $resolvedInterfaces)
{
return in_array($class, $resolvedInterfaces);
}

/**
* Splice the given value into the parameter list.
*
Expand Down

0 comments on commit 440ffeb

Please sign in to comment.