Go to file
Tim a854480ff1 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 @@
+<?php
+
+namespace Ardent\Undercurrent\Http;
+
+use Ardent\Undercurrent\Attribute\Route;
+
+class RouteConfig
+{
+    public function __construct(
+        private readonly Route  $route,
+        private readonly string $controller,
+        private readonly string $method
+    )
+    {
+    }
+
+    public function getRoute(): Route
+    {
+        return $this->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 @@
+<?php
+
+namespace Ardent\Undercurrent\Http;
+
+use Exception;
+
+class RouteNotFoundException extends Exception
+{
+    public function __construct(RequestInterface $request)
+    {
+        parent::__construct(sprintf(
+            'No controller found for uri: %s',
+            $request->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<RouteConfig>
+     */
+    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<RouteConfig>
+     */
+    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
2023-08-08 16:53:27 +02:00
app Implement basic version of route matching 2023-08-08 16:53:27 +02:00
public Properly implement the router with config and interfaces 2023-08-07 17:51:53 +02:00
src Implement basic version of route matching 2023-08-08 16:53:27 +02:00
.gitignore First working version with non working routes 2023-07-28 16:14:55 +02:00
composer.json Properly implement the router with config and interfaces 2023-08-07 17:51:53 +02:00
composer.lock Properly implement the router with config and interfaces 2023-08-07 17:51:53 +02:00
README.md Add response and request objects and interfaces 2023-08-07 14:23:00 +02:00

Todos:

  • Collect routes properly
  • Process routes correctly
  • Add request and response objects

Routing: Currently the routes are hardcoded, we need we way to process all classes maybe and sort them into a list of routes.