64 lines
1.6 KiB
PHP
64 lines
1.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Support;
|
|
|
|
final class Router
|
|
{
|
|
private array $routes = [];
|
|
|
|
public function __construct(private readonly Request $request)
|
|
{
|
|
}
|
|
|
|
public function get(string $path, callable $handler): void
|
|
{
|
|
$this->map('GET', $path, $handler);
|
|
}
|
|
|
|
public function post(string $path, callable $handler): void
|
|
{
|
|
$this->map('POST', $path, $handler);
|
|
}
|
|
|
|
public function patch(string $path, callable $handler): void
|
|
{
|
|
$this->map('PATCH', $path, $handler);
|
|
}
|
|
|
|
public function delete(string $path, callable $handler): void
|
|
{
|
|
$this->map('DELETE', $path, $handler);
|
|
}
|
|
|
|
public function dispatch(): void
|
|
{
|
|
$method = $this->request->method();
|
|
$path = $this->request->path();
|
|
|
|
foreach ($this->routes[$method] ?? [] as $route) {
|
|
$pattern = preg_replace('#\{([a-zA-Z_][a-zA-Z0-9_]*)\}#', '(?P<$1>[^/]+)', $route['path']);
|
|
$pattern = '#^' . $pattern . '$#';
|
|
|
|
if (!preg_match($pattern, $path, $matches)) {
|
|
continue;
|
|
}
|
|
|
|
$params = array_filter($matches, static fn (string|int $key): bool => is_string($key), ARRAY_FILTER_USE_KEY);
|
|
$route['handler']($this->request, $params);
|
|
return;
|
|
}
|
|
|
|
Response::json(['message' => 'Route not found', 'path' => $path], 404);
|
|
}
|
|
|
|
private function map(string $method, string $path, callable $handler): void
|
|
{
|
|
$this->routes[$method][] = [
|
|
'path' => rtrim($path, '/') ?: '/',
|
|
'handler' => $handler,
|
|
];
|
|
}
|
|
}
|