Skip to content

Commit 166912d

Browse files
authored
feat: multiple routes per controller method (#667)
1 parent 83f1dac commit 166912d

File tree

6 files changed

+42
-8
lines changed

6 files changed

+42
-8
lines changed

src/Tempest/Http/src/Get.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use Attribute;
88

9-
#[Attribute]
9+
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
1010
final class Get extends Route
1111
{
1212
public function __construct(

src/Tempest/Http/src/Post.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use Attribute;
88

9-
#[Attribute]
9+
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
1010
final class Post extends Route
1111
{
1212
public function __construct(

src/Tempest/Http/src/Route.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use Attribute;
88
use Tempest\Reflection\MethodReflector;
99

10-
#[Attribute]
10+
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
1111
class Route
1212
{
1313
public MethodReflector $handler;

src/Tempest/Http/src/RouteDiscovery.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,11 @@ public function __construct(
1818
public function discover(ClassReflector $class): void
1919
{
2020
foreach ($class->getPublicMethods() as $method) {
21-
$routeAttribute = $method->getAttribute(Route::class);
21+
$routeAttributes = $method->getAttributes(Route::class);
2222

23-
if (! $routeAttribute) {
24-
continue;
23+
foreach ($routeAttributes as $routeAttribute) {
24+
$this->routeConfig->addRoute($method, $routeAttribute);
2525
}
26-
27-
$this->routeConfig->addRoute($method, $routeAttribute);
2826
}
2927
}
3028

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Tempest\Fixtures\Controllers;
6+
7+
use Tempest\Http\Get;
8+
use Tempest\Http\Method;
9+
use Tempest\Http\Post;
10+
use Tempest\Http\Response;
11+
use Tempest\Http\Responses\Ok;
12+
use Tempest\Http\Route;
13+
14+
final readonly class ControllerWithRepeatedRoutes
15+
{
16+
#[Route('/repeated/a', Method::GET)]
17+
#[Route('/repeated/b', Method::GET)]
18+
#[Get('/repeated/c')]
19+
#[Get('/repeated/d')]
20+
#[Post('/repeated/e')]
21+
#[Post('/repeated/f')]
22+
public function __invoke(): Response
23+
{
24+
return new Ok();
25+
}
26+
}

tests/Integration/Route/RouterTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,14 @@ public function test_trailing_slash(): void
137137
->get('/test/1/a/')
138138
->assertOk();
139139
}
140+
141+
public function test_repeated_routes(): void
142+
{
143+
$this->http->get('/repeated/a')->assertOk();
144+
$this->http->get('/repeated/b')->assertOk();
145+
$this->http->get('/repeated/c')->assertOk();
146+
$this->http->get('/repeated/d')->assertOk();
147+
$this->http->post('/repeated/e')->assertOk();
148+
$this->http->post('/repeated/f')->assertOk();
149+
}
140150
}

0 commit comments

Comments
 (0)