ImplicitRouteBinding.php
TLDR
This file, ImplicitRouteBinding.php
, is part of the Illuminate Routing package in the Demo Projects project. It contains the ImplicitRouteBinding
class with methods to resolve implicit route bindings for a given route.
Methods
resolveForRoute
This method resolves the implicit route bindings for a given route. It takes a container and a route object as parameters. It iterates over the route's parameters and resolves the bindings based on the parameter type and value. It also handles nested route bindings and checks for soft deletes. If a binding cannot be resolved, it throws a ModelNotFoundException
or a BackedEnumCaseNotFoundException
.
resolveBackedEnumsForRoute
This protected method resolves the backed Enums route bindings for a route. It takes a route object and an array of parameters as parameters. It iterates over the route's parameters and resolves the bindings for parameters with a backedEnum
attribute. If a binding cannot be resolved, it throws a BackedEnumCaseNotFoundException
.
getParameterName
This protected method returns the parameter name if it exists in the given parameters array. It takes a name and an array of parameters as parameters. It checks if the name or its snake case version exists as a key in the parameters array and returns the matching name.
<?php
namespace Illuminate\Routing;
use Illuminate\Contracts\Routing\UrlRoutable;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException;
use Illuminate\Support\Reflector;
use Illuminate\Support\Str;
class ImplicitRouteBinding
{
/**
* Resolve the implicit route bindings for the given route.
*
* @param \Illuminate\Container\Container $container
* @param \Illuminate\Routing\Route $route
* @return void
*
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model>
* @throws \Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException
*/
public static function resolveForRoute($container, $route)
{
$parameters = $route->parameters();
$route = static::resolveBackedEnumsForRoute($route, $parameters);
foreach ($route->signatureParameters(['subClass' => UrlRoutable::class]) as $parameter) {
if (! $parameterName = static::getParameterName($parameter->getName(), $parameters)) {
continue;
}
$parameterValue = $parameters[$parameterName];
if ($parameterValue instanceof UrlRoutable) {
continue;
}
$instance = $container->make(Reflector::getParameterClassName($parameter));
$parent = $route->parentOfParameter($parameterName);
$routeBindingMethod = $route->allowsTrashedBindings() && in_array(SoftDeletes::class, class_uses_recursive($instance))
? 'resolveSoftDeletableRouteBinding'
: 'resolveRouteBinding';
if ($parent instanceof UrlRoutable &&
! $route->preventsScopedBindings() &&
($route->enforcesScopedBindings() || array_key_exists($parameterName, $route->bindingFields()))) {
$childRouteBindingMethod = $route->allowsTrashedBindings() && in_array(SoftDeletes::class, class_uses_recursive($instance))
? 'resolveSoftDeletableChildRouteBinding'
: 'resolveChildRouteBinding';
if (! $model = $parent->{$childRouteBindingMethod}(
$parameterName, $parameterValue, $route->bindingFieldFor($parameterName)
)) {
throw (new ModelNotFoundException)->setModel(get_class($instance), [$parameterValue]);
}
} elseif (! $model = $instance->{$routeBindingMethod}($parameterValue, $route->bindingFieldFor($parameterName))) {
throw (new ModelNotFoundException)->setModel(get_class($instance), [$parameterValue]);
}
$route->setParameter($parameterName, $model);
}
}
/**
* Resolve the Backed Enums route bindings for the route.
*
* @param \Illuminate\Routing\Route $route
* @param array $parameters
* @return \Illuminate\Routing\Route
*
* @throws \Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException
*/
protected static function resolveBackedEnumsForRoute($route, $parameters)
{
foreach ($route->signatureParameters(['backedEnum' => true]) as $parameter) {
if (! $parameterName = static::getParameterName($parameter->getName(), $parameters)) {
continue;
}
$parameterValue = $parameters[$parameterName];
$backedEnumClass = $parameter->getType()?->getName();
$backedEnum = $backedEnumClass::tryFrom((string) $parameterValue);
if (is_null($backedEnum)) {
throw new BackedEnumCaseNotFoundException($backedEnumClass, $parameterValue);
}
$route->setParameter($parameterName, $backedEnum);
}
return $route;
}
/**
* Return the parameter name if it exists in the given parameters.
*
* @param string $name
* @param array $parameters
* @return string|null
*/
protected static function getParameterName($name, $parameters)
{
if (array_key_exists($name, $parameters)) {
return $name;
}
if (array_key_exists($snakedName = Str::snake($name), $parameters)) {
return $snakedName;
}
}
}