Files
elixforms-web-services/src/Api/Core/Router.php
T

66 lines
2.2 KiB
PHP

<?php
namespace Api\Core;
class Router {
private $routes = [];
private $container;
public function __construct(Container $container) {
$this->container = $container;
}
public function register($method, $path, $handler) {
$this->routes[$method][$path] = $handler;
}
public function get($path, $handler) { $this->register('GET', $path, $handler); }
public function post($path, $handler) { $this->register('POST', $path, $handler); }
private function normalizePath(string $path): string {
$path = '/' . trim($path, '/');
$path = preg_replace('#^/api(?=/|$)#i', '', $path);
$path = '/' . trim($path, '/');
return $path === '' ? '/' : $path;
}
public function dispatch(Request $req, Response $res) {
$method = $req->method();
$path = $this->normalizePath($req->path());
// extract version prefix /v1/...
if (preg_match('#^/v([0-9]+)(/.*)?$#', $path, $m)) {
$version = $m[1];
$pathWithoutVersion = $m[2] ?? '/';
} else {
$version = '1';
$pathWithoutVersion = $path;
}
// try exact route with versioned namespace
$routeKey = $pathWithoutVersion;
if (!isset($this->routes[$method][$routeKey])) {
return $res->json(['error' => 'Not found'], 404);
}
$handler = $this->routes[$method][$routeKey];
// handler can be 'UsersController@index' or 'Controllers\\UsersController@index'
if (strpos($handler, '@') !== false) {
list($class, $function) = explode('@', $handler);
// if class not namespaced, prefix with Api\\Controllers\\V{n}\\
if (strpos($class, '\\') === false) {
$class = "Api\\Controllers\\V{$version}\\" . $class;
}
} else {
return $res->json(['error' => 'Invalid handler'], 500);
}
if (!class_exists($class)) {
return $res->json(['error' => 'Controller not found'], 500);
}
$controller = $this->container->make($class);
return $controller->$function($req, $res);
}
}