From a854480ff1ab3fba94c0b3b10332d18e3b64cc08 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 8 Aug 2023 16:53:27 +0200 Subject: [PATCH] Implement basic version of route matching Make RouteConfig more readable diff --git a/app/Kernel.php b/app/Kernel.php index 4425355..a365d39 100644 --- a/app/Kernel.php +++ b/app/Kernel.php @@ -10,7 +10,7 @@ class Kernel extends BaseKernel { protected function dependencies(ContainerInterface $container): void { - $this->addRoutes($container, [ + $this->addControllers($container, [ BaseController::class, ]); } diff --git a/src/Attribute/Route.php b/src/Attribute/Route.php index 6bbd272..7129654 100644 --- a/src/Attribute/Route.php +++ b/src/Attribute/Route.php @@ -2,13 +2,15 @@ namespace Ardent\Undercurrent\Attribute; +use Ardent\Undercurrent\Http\MethodEnum; use Attribute; #[Attribute] class Route { public function __construct( - public string $path, + public string $path, + public ?MethodEnum $method = null, ) { } diff --git a/src/Http/GenericRouter.php b/src/Http/GenericRouter.php index fa1bc6a..73ce8f1 100644 --- a/src/Http/GenericRouter.php +++ b/src/Http/GenericRouter.php @@ -11,15 +11,21 @@ class GenericRouter implements RouterInterface { public function __construct( private readonly ContainerInterface $container, - private readonly RouterConfig $config, + private readonly RouterConfig $config, ) { } public function dispatch(RequestInterface $request): ResponseInterface { - $controller = $this->container->get(BaseController::class); - $method = 'helloWorld'; - return $controller->$method(); + foreach ($this->config->getRoutes() as $route) { + if ($route->getRoute()->path === $request->getUri()) { + $controller = $this->container->get($route->getController()); + $method = $route->getMethod(); + return $controller->$method(); + } + } + + throw new RouteNotFoundException($request); } } \ No newline at end of file diff --git a/src/Http/RouteConfig.php b/src/Http/RouteConfig.php new file mode 100644 index 0000000..00c2cb0 --- /dev/null +++ b/src/Http/RouteConfig.php @@ -0,0 +1,31 @@ +route; + } + + public function getController(): string + { + return $this->controller; + } + + public function getMethod(): string + { + return $this->method; + } +} \ No newline at end of file diff --git a/src/Http/RouteNotFoundException.php b/src/Http/RouteNotFoundException.php new file mode 100644 index 0000000..081c625 --- /dev/null +++ b/src/Http/RouteNotFoundException.php @@ -0,0 +1,16 @@ +getUri() + )); + } +} \ No newline at end of file diff --git a/src/Http/RouterConfig.php b/src/Http/RouterConfig.php index 60e5af7..eec5cde 100644 --- a/src/Http/RouterConfig.php +++ b/src/Http/RouterConfig.php @@ -2,16 +2,45 @@ namespace Ardent\Undercurrent\Http; +use Ardent\Undercurrent\Attribute\Route; +use ReflectionAttribute; +use ReflectionClass; + class RouterConfig { - public function __construct( - private readonly array $controllers = [], - ) + /** + * @var array + */ + private array $routes = []; + + public function addController(string $controller): self { + $reflectionClass = new ReflectionClass($controller); + + foreach ($reflectionClass->getMethods() as $method) { + $attributes = $method->getAttributes(Route::class, ReflectionAttribute::IS_INSTANCEOF); + + if (count($attributes) === 0) { + continue; + } + + $route = $attributes[0]->newInstance(); + + $this->routes[] = new RouteConfig( + $route, + $controller, + $method->getName(), + ); + } + + return $this; } - public function getControllers(): array + /** + * @return array + */ + public function getRoutes(): array { - return $this->controllers; + return $this->routes; } } \ No newline at end of file diff --git a/src/Kernel/BaseKernel.php b/src/Kernel/BaseKernel.php index 149aa8b..7122dcc 100644 --- a/src/Kernel/BaseKernel.php +++ b/src/Kernel/BaseKernel.php @@ -38,13 +38,16 @@ class BaseKernel echo $router->dispatch($request)->getBody(); } - protected function addRoutes(ContainerInterface $container, array $routes): void + protected function addControllers(ContainerInterface $container, array $controllers): void { - foreach ($routes as $route) { - $container->add($route); + $config = new RouterConfig(); + + foreach ($controllers as $controller) { + $container->add($controller); + $config->addController($controller); } - $container->add(RouterConfig::class, fn() => new RouterConfig($routes)); + $container->add(RouterConfig::class, fn() => $config); } protected function dependencies(ContainerInterface $container): void --- app/Kernel.php | 2 +- src/Attribute/Route.php | 4 ++- src/Http/GenericRouter.php | 14 ++++++++--- src/Http/RouteConfig.php | 31 +++++++++++++++++++++++ src/Http/RouteNotFoundException.php | 16 ++++++++++++ src/Http/RouterConfig.php | 39 +++++++++++++++++++++++++---- src/Kernel/BaseKernel.php | 11 +++++--- 7 files changed, 102 insertions(+), 15 deletions(-) create mode 100644 src/Http/RouteConfig.php create mode 100644 src/Http/RouteNotFoundException.php diff --git a/app/Kernel.php b/app/Kernel.php index 4425355..a365d39 100644 --- a/app/Kernel.php +++ b/app/Kernel.php @@ -10,7 +10,7 @@ class Kernel extends BaseKernel { protected function dependencies(ContainerInterface $container): void { - $this->addRoutes($container, [ + $this->addControllers($container, [ BaseController::class, ]); } diff --git a/src/Attribute/Route.php b/src/Attribute/Route.php index 6bbd272..7129654 100644 --- a/src/Attribute/Route.php +++ b/src/Attribute/Route.php @@ -2,13 +2,15 @@ namespace Ardent\Undercurrent\Attribute; +use Ardent\Undercurrent\Http\MethodEnum; use Attribute; #[Attribute] class Route { public function __construct( - public string $path, + public string $path, + public ?MethodEnum $method = null, ) { } diff --git a/src/Http/GenericRouter.php b/src/Http/GenericRouter.php index fa1bc6a..73ce8f1 100644 --- a/src/Http/GenericRouter.php +++ b/src/Http/GenericRouter.php @@ -11,15 +11,21 @@ class GenericRouter implements RouterInterface { public function __construct( private readonly ContainerInterface $container, - private readonly RouterConfig $config, + private readonly RouterConfig $config, ) { } public function dispatch(RequestInterface $request): ResponseInterface { - $controller = $this->container->get(BaseController::class); - $method = 'helloWorld'; - return $controller->$method(); + foreach ($this->config->getRoutes() as $route) { + if ($route->getRoute()->path === $request->getUri()) { + $controller = $this->container->get($route->getController()); + $method = $route->getMethod(); + return $controller->$method(); + } + } + + throw new RouteNotFoundException($request); } } \ No newline at end of file diff --git a/src/Http/RouteConfig.php b/src/Http/RouteConfig.php new file mode 100644 index 0000000..00c2cb0 --- /dev/null +++ b/src/Http/RouteConfig.php @@ -0,0 +1,31 @@ +route; + } + + public function getController(): string + { + return $this->controller; + } + + public function getMethod(): string + { + return $this->method; + } +} \ No newline at end of file diff --git a/src/Http/RouteNotFoundException.php b/src/Http/RouteNotFoundException.php new file mode 100644 index 0000000..081c625 --- /dev/null +++ b/src/Http/RouteNotFoundException.php @@ -0,0 +1,16 @@ +getUri() + )); + } +} \ No newline at end of file diff --git a/src/Http/RouterConfig.php b/src/Http/RouterConfig.php index 60e5af7..eec5cde 100644 --- a/src/Http/RouterConfig.php +++ b/src/Http/RouterConfig.php @@ -2,16 +2,45 @@ namespace Ardent\Undercurrent\Http; +use Ardent\Undercurrent\Attribute\Route; +use ReflectionAttribute; +use ReflectionClass; + class RouterConfig { - public function __construct( - private readonly array $controllers = [], - ) + /** + * @var array + */ + private array $routes = []; + + public function addController(string $controller): self { + $reflectionClass = new ReflectionClass($controller); + + foreach ($reflectionClass->getMethods() as $method) { + $attributes = $method->getAttributes(Route::class, ReflectionAttribute::IS_INSTANCEOF); + + if (count($attributes) === 0) { + continue; + } + + $route = $attributes[0]->newInstance(); + + $this->routes[] = new RouteConfig( + $route, + $controller, + $method->getName(), + ); + } + + return $this; } - public function getControllers(): array + /** + * @return array + */ + public function getRoutes(): array { - return $this->controllers; + return $this->routes; } } \ No newline at end of file diff --git a/src/Kernel/BaseKernel.php b/src/Kernel/BaseKernel.php index 149aa8b..7122dcc 100644 --- a/src/Kernel/BaseKernel.php +++ b/src/Kernel/BaseKernel.php @@ -38,13 +38,16 @@ class BaseKernel echo $router->dispatch($request)->getBody(); } - protected function addRoutes(ContainerInterface $container, array $routes): void + protected function addControllers(ContainerInterface $container, array $controllers): void { - foreach ($routes as $route) { - $container->add($route); + $config = new RouterConfig(); + + foreach ($controllers as $controller) { + $container->add($controller); + $config->addController($controller); } - $container->add(RouterConfig::class, fn() => new RouterConfig($routes)); + $container->add(RouterConfig::class, fn() => $config); } protected function dependencies(ContainerInterface $container): void