diff --git a/src/Illuminate/Routing/ImplicitRouteBinding.php b/src/Illuminate/Routing/ImplicitRouteBinding.php index d9978af3193a..d3590de1d707 100644 --- a/src/Illuminate/Routing/ImplicitRouteBinding.php +++ b/src/Illuminate/Routing/ImplicitRouteBinding.php @@ -84,7 +84,7 @@ protected static function resolveBackedEnumsForRoute($route, $parameters) $parameterValue = $parameters[$parameterName]; - $backedEnumClass = (string) $parameter->getType(); + $backedEnumClass = $parameter->getType()?->getName(); $backedEnum = $backedEnumClass::tryFrom((string) $parameterValue); diff --git a/src/Illuminate/Support/Reflector.php b/src/Illuminate/Support/Reflector.php index 0282378631d7..3f153bf3bf84 100644 --- a/src/Illuminate/Support/Reflector.php +++ b/src/Illuminate/Support/Reflector.php @@ -148,7 +148,11 @@ public static function isParameterSubclassOf($parameter, $className) */ public static function isParameterBackedEnumWithStringBackingType($parameter) { - $backedEnumClass = (string) $parameter->getType(); + $backedEnumClass = $parameter->getType()?->getName(); + + if (is_null($backedEnumClass)) { + return false; + } if (enum_exists($backedEnumClass)) { $reflectionBackedEnum = new ReflectionEnum($backedEnumClass); diff --git a/tests/Routing/ImplicitRouteBindingTest.php b/tests/Routing/ImplicitRouteBindingTest.php index 909af4be3e78..675196a11364 100644 --- a/tests/Routing/ImplicitRouteBindingTest.php +++ b/tests/Routing/ImplicitRouteBindingTest.php @@ -31,6 +31,24 @@ public function test_it_can_resolve_the_implicit_backed_enum_route_bindings_for_ $this->assertSame('fruits', $route->parameter('category')->value); } + public function test_it_can_resolve_the_implicit_backed_enum_route_bindings_for_the_given_route_with_optional_parameter() + { + $action = ['uses' => function (?CategoryBackedEnum $category = null) { + return $category->value; + }]; + + $route = new Route('GET', '/test', $action); + $route->parameters = ['category' => 'fruits']; + + $route->prepareForSerialization(); + + $container = Container::getInstance(); + + ImplicitRouteBinding::resolveForRoute($container, $route); + + $this->assertSame('fruits', $route->parameter('category')->value); + } + public function test_it_does_not_resolve_implicit_non_backed_enum_route_bindings_for_the_given_route() { $action = ['uses' => function (CategoryEnum $category) { diff --git a/tests/Routing/RoutingRouteTest.php b/tests/Routing/RoutingRouteTest.php index 5a1a675d5cf5..e9d58b075e2b 100644 --- a/tests/Routing/RoutingRouteTest.php +++ b/tests/Routing/RoutingRouteTest.php @@ -1893,6 +1893,20 @@ public function testImplicitBindingsWithOptionalParameterWithNoKeyInUri() $router->dispatch(Request::create('foo', 'GET'))->getContent(); } + public function testImplicitBindingsWithOptionalParameterUsingEnumIsAlwaysCastedToEnum() + { + include_once 'enums.php'; + + $router = $this->getRouter(); + $router->get('foo/{bar?}', [ + 'middleware' => SubstituteBindings::class, + 'uses' => function (?\Illuminate\Tests\Routing\CategoryBackedEnum $bar = null) { + $this->assertInstanceOf(CategoryBackedEnum::class, $bar); + }, + ]); + $router->dispatch(Request::create('foo/people', 'GET'))->getContent(); + } + public function testImplicitBindingsWithOptionalParameterWithNonExistingKeyInUri() { $this->expectException(ModelNotFoundException::class);