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
This commit is contained in:
Tim 2023-08-08 16:53:27 +02:00
parent 96e833fb4b
commit a854480ff1
7 changed files with 102 additions and 15 deletions

View File

@ -10,7 +10,7 @@ class Kernel extends BaseKernel
{
protected function dependencies(ContainerInterface $container): void
{
$this->addRoutes($container, [
$this->addControllers($container, [
BaseController::class,
]);
}

View File

@ -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,
)
{
}

View File

@ -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);
}
}

31
src/Http/RouteConfig.php Normal file
View File

@ -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;
}
}

View File

@ -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()
));
}
}

View File

@ -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;
}
}

View File

@ -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