Skip to content

Commit 65894b2

Browse files
add route pattern to Router class
1 parent 4afb2a9 commit 65894b2

File tree

3 files changed

+116
-7
lines changed

3 files changed

+116
-7
lines changed

app/Core/Database.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use PDO;
6+
7+
namespace PHPAether\Core\Database;
8+
9+
class Database
10+
{
11+
12+
protected ?PDO $conn = null;
13+
14+
private function __construct()
15+
{
16+
}
17+
18+
public static function getInstance(): self
19+
{
20+
if (is_null($this->conn)) {
21+
$this->conn = new PDO("");
22+
}
23+
24+
return new static();
25+
}
26+
27+
// Forward all method call to PDO methods
28+
29+
}

app/Core/Router.php

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,14 @@ public function getRegisteredRoutes(): array
4040
public function route(Request $request): array
4141
{
4242

43-
// Check if route info is found
44-
if (! ($requestRouteInfo = $this->routes[$request->route] ?? null)) {
43+
$matchedRoute = $this->matchRequestRoute($request->route);
44+
if ($matchedRoute === null) {
4545
return ['Error', 'notFound'];
4646
}
4747

48-
$requestRouteInfo = $this->parseRouteInfo($requestRouteInfo, $request->method);
48+
$requestRouteInfo = $this->parseRouteInfo(
49+
$this->routes[$matchedRoute], $request->method
50+
);
4951

5052
// Get the controller
5153
$controller = $requestRouteInfo['controller'];
@@ -54,7 +56,73 @@ public function route(Request $request): array
5456
return [$controller, $action];
5557
}
5658

57-
private function parseRouteInfo(array $routeInfo, string $requestMethod): ?array
59+
private function matchRequestRoute(string $requestRoute): ?string
60+
{
61+
62+
foreach ($this->routes as $route => $routeInfo) {
63+
if ($route === $requestRoute) {
64+
return $route;
65+
}
66+
67+
if ($this->routeIsRoutePattern($route)) {
68+
69+
$routeParams = $this->getRoutePatternParameters($route);
70+
$routePatternRegex = $this->buildRoutePatternRegex($route, $routeParams);
71+
72+
if (preg_match($routePatternRegex, $requestRoute)) {
73+
return $route;
74+
}
75+
}
76+
}
77+
78+
return null;
79+
}
80+
81+
private function buildRoutePatternRegex(
82+
string $routePattern,
83+
array $routeParams
84+
)
85+
{
86+
$regexStr = implode("/", array_map(function (string $chunk) use ($routeParams) {
87+
if (
88+
$chunk[0] === ':' &&
89+
($param = substr($chunk, 1)) &&
90+
($paramInfo = $routeParams[$param] ?? null)
91+
) {
92+
$paramType = $paramInfo['type'] ?? "string";
93+
return match($paramType) {
94+
"string" => "\w+",
95+
"number" => "\d+",
96+
default => "\w+"
97+
};
98+
99+
}
100+
101+
return $chunk;
102+
}, explode("/", $routePattern)));
103+
104+
return "@$regexStr@";
105+
}
106+
107+
private function getRoutePatternParameters(
108+
string $route
109+
)
110+
{
111+
return $this->routes[$route]['parameters'] ?? [];
112+
}
113+
114+
private function routeIsRoutePattern(
115+
string $route
116+
)
117+
{
118+
119+
return ! is_null($this->routes[$route]['parameters'] ?? null);
120+
}
121+
122+
123+
private function parseRouteInfo(
124+
array $routeInfo,
125+
string $requestMethod): ?array
58126
{
59127

60128
$getRouteParams = function (string $param) use ($routeInfo, $requestMethod) {
@@ -81,4 +149,4 @@ private function parseRouteInfo(array $routeInfo, string $requestMethod): ?array
81149

82150

83151

84-
}
152+
}

tests/MockHTTPRequestTestCase.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ class MockHTTPRequestTestCase extends TestCase
3939
'/user/dashboard' => [
4040
'controller' => 'User',
4141
'action' => 'userDashboardView'
42+
],
43+
'book/:id/edit' => [
44+
'controller' => 'Book',
45+
'action' => 'editBook',
46+
'methods' => ['POST', 'PUT'],
47+
'parameters' => [
48+
'id' => [
49+
'type' => 'number',
50+
]
51+
]
4252
]
4353
];
4454

@@ -107,9 +117,11 @@ public static function httpGETRequestDataProvider(): array
107117
['/', '/', ['Home', 'index'], ''],
108118
['/login?r_url=/user/dashboard', '/login', ['Auth', 'loginView'], ''],
109119
['/user/dashboard', '/user/dashboard', ['User', 'userDashboardView'], ''],
110-
['/leaderboard?league=ruby', '/leaderboard', ['Error', 'notFound'], '']
120+
['/leaderboard?league=ruby', '/leaderboard', ['Error', 'notFound'], ''],
121+
['/book/3/edit', '/book/3/edit', ['Book', 'editBook'], '']
111122
];
112123
}
124+
113125
public static function httpPOSTRequestDataProvider(): array
114126
{
115127
return [
@@ -128,4 +140,4 @@ public static function httpPUTRequestDataProvider(): array
128140
];
129141
}
130142

131-
}
143+
}

0 commit comments

Comments
 (0)