diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index fac41b5e638f2..03be882faf995 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.3 +--- + + * Add FQCN and FQCN::method aliases for routes loaded from attributes/annotations when applicable + 6.2 --- diff --git a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php index decd2a2b1d60c..ed3f85cc0253a 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php @@ -125,10 +125,20 @@ public function load(mixed $class, string $type = null): RouteCollection return $collection; } + $fqcnAlias = false; foreach ($class->getMethods() as $method) { $this->defaultRouteIndex = 0; + $routeNamesBefore = array_keys($collection->all()); foreach ($this->getAnnotations($method) as $annot) { $this->addRoute($collection, $annot, $globals, $class, $method); + if ('__invoke' === $method->name) { + $fqcnAlias = true; + } + } + + if (1 === $collection->count() - \count($routeNamesBefore)) { + $newRouteName = current(array_diff(array_keys($collection->all()), $routeNamesBefore)); + $collection->addAlias(sprintf('%s::%s', $class->name, $method->name), $newRouteName); } } @@ -136,9 +146,15 @@ public function load(mixed $class, string $type = null): RouteCollection $globals = $this->resetGlobals(); foreach ($this->getAnnotations($class) as $annot) { $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); + $fqcnAlias = true; } } + if ($fqcnAlias && 1 === $collection->count()) { + $collection->addAlias($class->name, $invokeRouteName = key($collection->all())); + $collection->addAlias(sprintf('%s::__invoke', $class->name), $invokeRouteName); + } + return $collection; } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/InvokableMethodController.php b/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/InvokableMethodController.php new file mode 100644 index 0000000000000..08986249305f0 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/AnnotationFixtures/InvokableMethodController.php @@ -0,0 +1,15 @@ +loader->load($this->getNamespace().'\ActionPathController'); $this->assertCount(1, $routes); $this->assertEquals('/path', $routes->get('action')->getPath()); + $this->assertEquals(new Alias('action'), $routes->getAlias($this->getNamespace().'\ActionPathController::action')); } public function testRequirementsWithoutPlaceholderName() @@ -72,6 +74,19 @@ public function testInvokableControllerLoader() $this->assertEquals('/here', $routes->get('lol')->getPath()); $this->assertEquals(['GET', 'POST'], $routes->get('lol')->getMethods()); $this->assertEquals(['https'], $routes->get('lol')->getSchemes()); + $this->assertEquals(new Alias('lol'), $routes->getAlias($this->getNamespace().'\InvokableController')); + $this->assertEquals(new Alias('lol'), $routes->getAlias($this->getNamespace().'\InvokableController::__invoke')); + } + + public function testInvokableMethodControllerLoader() + { + $routes = $this->loader->load($this->getNamespace().'\InvokableMethodController'); + $this->assertCount(1, $routes); + $this->assertEquals('/here', $routes->get('lol')->getPath()); + $this->assertEquals(['GET', 'POST'], $routes->get('lol')->getMethods()); + $this->assertEquals(['https'], $routes->get('lol')->getSchemes()); + $this->assertEquals(new Alias('lol'), $routes->getAlias($this->getNamespace().'\InvokableMethodController')); + $this->assertEquals(new Alias('lol'), $routes->getAlias($this->getNamespace().'\InvokableMethodController::__invoke')); } public function testInvokableLocalizedControllerLoading() @@ -119,6 +134,8 @@ public function testMethodActionControllers() $this->assertSame(['put', 'post'], array_keys($routes->all())); $this->assertEquals('/the/path', $routes->get('put')->getPath()); $this->assertEquals('/the/path', $routes->get('post')->getPath()); + $this->assertEquals(new Alias('post'), $routes->getAlias($this->getNamespace().'\MethodActionControllers::post')); + $this->assertEquals(new Alias('put'), $routes->getAlias($this->getNamespace().'\MethodActionControllers::put')); } public function testInvokableClassRouteLoadWithMethodAnnotation()