|
797cbedb27
|
Add route to create book
|
2023-08-17 15:53:58 +02:00 |
|
|
f8d1c66934
|
Implement commands
|
2023-08-16 16:04:35 +02:00 |
|
|
59200be680
|
Add doctrine and seperate out the renderer
|
2023-08-16 14:28:06 +02:00 |
|
|
18848e041f
|
Play around with the rendering
|
2023-08-15 13:56:04 +02:00 |
|
|
24683e70a8
|
Streamline view rendering
|
2023-08-15 13:37:03 +02:00 |
|
|
45797ba20a
|
Add ViewHelper in view for injecting some basic classes in views
|
2023-08-15 12:10:04 +02:00 |
|
|
c80dcd2860
|
Implement simple PHP based view renderer
|
2023-08-15 03:05:28 +02:00 |
|
|
42c590dfd6
|
Finalize routing with injection and parameters
diff --git a/app/Controller/HelloWorldController.php b/app/Controller/HelloWorldController.php
index 7f2af8b..86c5b8e 100644
--- a/app/Controller/HelloWorldController.php
+++ b/app/Controller/HelloWorldController.php
@@ -28,13 +28,13 @@ class HelloWorldController
return new GenericResponse('Hello World!');
}
- #[Route('/routes')]
- public function routes(RouterConfig $config): ResponseInterface
+ #[Route('/routes/{word}')]
+ public function routes(RouterConfig $config, string $word): ResponseInterface
{
$routes = implode('<br>', array_map(
- fn($route) => sprintf('%s - %s->%s', $route->getRoute()->path, $route->getController(), $route->getMethod()),
- $config->getRoutes()
- ));
+ fn($route) => sprintf('%s - %s->%s', $route->getRoute()->path, $route->getController(), $route->getMethod()),
+ $config->getRoutes()
+ )) . "<br>$word";
return new GenericResponse($routes);
}
diff --git a/src/Container/ContainerInterface.php b/src/Container/ContainerInterface.php
index 7b55a94..5119eb5 100644
--- a/src/Container/ContainerInterface.php
+++ b/src/Container/ContainerInterface.php
@@ -19,4 +19,6 @@ interface ContainerInterface
* @throws ClassNotFoundException
*/
public function get(string $className): object;
+
+ public function call(string $className, string $methodName, array $parameters = []): mixed;
}
\ No newline at end of file
diff --git a/src/Container/GenericContainer.php b/src/Container/GenericContainer.php
index 8fdb26e..0e467b6 100644
--- a/src/Container/GenericContainer.php
+++ b/src/Container/GenericContainer.php
@@ -2,8 +2,10 @@
namespace Ardent\Undercurrent\Container;
+use Ardent\Undercurrent\Http\RouteConfig;
use Exception;
use ReflectionClass;
+use ReflectionMethod;
class GenericContainer implements ContainerInterface
{
@@ -61,23 +63,39 @@ class GenericContainer implements ContainerInterface
return $instance;
}
+ public function call(string $className, string $methodName, array $parameters = []): mixed
+ {
+ $params = $this->methodParams($className, $methodName, $parameters) + $parameters;
+ return $this->get($className)->$methodName(...$params);
+ }
+
private function autowire(string $className): ?object
{
$reflection = new ReflectionClass($className);
- $constructor = $reflection->getConstructor();
- if (!$constructor) {
+ $reflectionMethod = $reflection->getConstructor();
+ if (!$reflectionMethod) {
return new $className();
}
+ return new $className(...$this->methodParams($className, $reflectionMethod->getName()));
+ }
+
+ private function methodParams(string $className, string $methodName, array $exceptParams = []): array
+ {
+ $reflectionMethod = new ReflectionMethod($className, $methodName);
+
$params = [];
- foreach ($constructor->getParameters() as $parameter) {
+ foreach ($reflectionMethod->getParameters() as $parameter) {
+ if (in_array($parameter->getName(), array_keys($exceptParams))) {
+ continue;
+ }
$type = $parameter->getType();
if (!$type) {
- throw new Exception("Parameter {$parameter->getName()} in $className has no type");
+ throw new Exception('Cannot autowire parameter without type');
}
$params[] = $this->get($type->getName());
}
- return new $className(...$params);
+ return $params;
}
}
\ No newline at end of file
diff --git a/src/Http/GenericRouter.php b/src/Http/GenericRouter.php
index d5ffb95..334ecac 100644
--- a/src/Http/GenericRouter.php
+++ b/src/Http/GenericRouter.php
@@ -17,7 +17,7 @@ class GenericRouter implements RouterInterface
}
/**
- * @throws RouteNotFoundException|ClassNotFoundException
+ * @throws RouteNotFoundException
*/
public function dispatch(RequestInterface $request): ResponseInterface
{
@@ -28,11 +28,11 @@ class GenericRouter implements RouterInterface
continue;
}
- $controller = $this->container->get($route->getController());
- $method = $route->getMethod();
-// $params = $this->autowire($route) + $this->resolveParams($route->getRoute()->path, $request->getUri());
- $params = $this->resolveParams($route->getRoute()->path, $request->getUri());
- return $controller->$method(...$params);
+ return $this->container->call(
+ $route->getController(),
+ $route->getMethod(),
+ $params,
+ );
}
throw new RouteNotFoundException($request);
@@ -40,6 +40,10 @@ class GenericRouter implements RouterInterface
private function resolveParams(string $routeUri, string $requestUri): ?array
{
+ if ($routeUri === $requestUri) {
+ return [];
+ }
+
$result = preg_match_all('/{(\w+)}/', $routeUri, $tokens);
if (!$result) {
@@ -55,27 +59,11 @@ class GenericRouter implements RouterInterface
) . '$/';
$result = preg_match($matchingRegex, $requestUri, $matches);
- if ($result === 0) {
- return [];
+ if (!$result) {
+ return null;
}
$matches = array_slice($matches, 1);
return array_combine(array_map(fn($token) => trim($token, '{}'), $tokens), $matches);
}
-
- private function autowire(RouteConfig $route): array
- {
- $reflectionMethod = new ReflectionMethod($route->getController(), $route->getMethod());
-
- $params = [];
- foreach ($reflectionMethod->getParameters() as $parameter) {
- $type = $parameter->getType();
- if (!$type) {
- throw new Exception('Cannot autowire parameter without type');
- }
- $params[] = $this->container->get($type->getName());
- }
-
- return $params;
- }
}
\ No newline at end of file
|
2023-08-10 17:57:25 +02:00 |
|
|
6f247f3ab7
|
Make route debug more readable
|
2023-08-09 00:59:07 +02:00 |
|
|
64ff0c243d
|
Add controller method autowiring
diff --git a/app/Controller/HelloWorldController.php b/app/Controller/HelloWorldController.php
index 8361e9d..282a990 100644
--- a/app/Controller/HelloWorldController.php
+++ b/app/Controller/HelloWorldController.php
@@ -5,6 +5,7 @@ namespace App\Controller;
use Ardent\Undercurrent\Attribute\Route;
use Ardent\Undercurrent\Http\GenericResponse;
use Ardent\Undercurrent\Http\ResponseInterface;
+use Ardent\Undercurrent\Http\RouterConfig;
use Ardent\Undercurrent\Http\StatusEnum;
class HelloWorldController
@@ -26,4 +27,21 @@ class HelloWorldController
{
return new GenericResponse('Hello World!');
}
+
+ #[Route('/routes')]
+ public function routes(RouterConfig $config): ResponseInterface
+ {
+ $routes = implode('<br>', array_map(
+ fn($route) => $route->getRoute()->path,
+ $config->getRoutes()
+ ));
+
+ return new GenericResponse($routes);
+ }
+
+ #[Route('/world/{name}')]
+ public function world(string $name): ResponseInterface
+ {
+ return new GenericResponse("Hello $name!");
+ }
}
\ No newline at end of file
diff --git a/src/Http/GenericRouter.php b/src/Http/GenericRouter.php
index b2d8e1d..23e9311 100644
--- a/src/Http/GenericRouter.php
+++ b/src/Http/GenericRouter.php
@@ -4,6 +4,8 @@ namespace Ardent\Undercurrent\Http;
use Ardent\Undercurrent\Container\ClassNotFoundException;
use Ardent\Undercurrent\Container\ContainerInterface;
+use Exception;
+use ReflectionMethod;
class GenericRouter implements RouterInterface
{
@@ -23,10 +25,26 @@ class GenericRouter implements RouterInterface
if ($route->getRoute()->path === $request->getUri()) {
$controller = $this->container->get($route->getController());
$method = $route->getMethod();
- return $controller->$method();
+ return $controller->$method(...$this->autowire($route));
}
}
throw new RouteNotFoundException($request);
}
+
+ private function autowire(RouteConfig $route): array
+ {
+ $reflectionMethod = new ReflectionMethod($route->getController(), $route->getMethod());
+
+ $params = [];
+ foreach ($reflectionMethod->getParameters() as $parameter) {
+ $type = $parameter->getType();
+ if (!$type) {
+ throw new Exception('Cannot autowire parameter without type');
+ }
+ $params[] = $this->container->get($type->getName());
+ }
+
+ return $params;
+ }
}
\ No newline at end of file
|
2023-08-09 00:49:47 +02:00 |
|
|
5d6ad29db8
|
Expand the response with headers and set status code
diff --git a/app/Controller/BaseController.php b/app/Controller/BaseController.php
deleted file mode 100644
index 8e24148..0000000
--- a/app/Controller/BaseController.php
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
-namespace App\Controller;
-
-use Ardent\Undercurrent\Attribute\Route;
-use Ardent\Undercurrent\Http\GenericResponse;
-use Ardent\Undercurrent\Http\ResponseInterface;
-
-class BaseController
-{
- #[Route('/hello')]
- public function helloWorld(): ResponseInterface
- {
- return new GenericResponse('Hello World!');
- }
-}
\ No newline at end of file
diff --git a/app/Controller/HelloWorldController.php b/app/Controller/HelloWorldController.php
new file mode 100644
index 0000000..8361e9d
--- /dev/null
+++ b/app/Controller/HelloWorldController.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Controller;
+
+use Ardent\Undercurrent\Attribute\Route;
+use Ardent\Undercurrent\Http\GenericResponse;
+use Ardent\Undercurrent\Http\ResponseInterface;
+use Ardent\Undercurrent\Http\StatusEnum;
+
+class HelloWorldController
+{
+ #[Route('/')]
+ public function index(): ResponseInterface
+ {
+ return new GenericResponse('Index, <a href="/hello">Hello</a>');
+ }
+
+ #[Route('/error')]
+ public function error(): ResponseInterface
+ {
+ return new GenericResponse('error', StatusEnum::NOT_FOUND);
+ }
+
+ #[Route('/hello')]
+ public function hello(): ResponseInterface
+ {
+ return new GenericResponse('Hello World!');
+ }
+}
\ No newline at end of file
diff --git a/app/Kernel.php b/app/Kernel.php
index a365d39..8b28577 100644
--- a/app/Kernel.php
+++ b/app/Kernel.php
@@ -2,7 +2,7 @@
namespace App;
-use App\Controller\BaseController;
+use App\Controller\HelloWorldController;
use Ardent\Undercurrent\Container\ContainerInterface;
use Ardent\Undercurrent\Kernel\BaseKernel;
@@ -11,7 +11,7 @@ class Kernel extends BaseKernel
protected function dependencies(ContainerInterface $container): void
{
$this->addControllers($container, [
- BaseController::class,
+ HelloWorldController::class,
]);
}
}
\ No newline at end of file
diff --git a/src/Container/ContainerInterface.php b/src/Container/ContainerInterface.php
index bd50325..7b55a94 100644
--- a/src/Container/ContainerInterface.php
+++ b/src/Container/ContainerInterface.php
@@ -16,7 +16,7 @@ interface ContainerInterface
* @template TClassName
* @param class-string<TClassName> $className
* @return TClassName
- * @throws Exception
+ * @throws ClassNotFoundException
*/
public function get(string $className): object;
}
\ No newline at end of file
diff --git a/src/Http/GenericResponse.php b/src/Http/GenericResponse.php
index d80d350..18852ff 100644
--- a/src/Http/GenericResponse.php
+++ b/src/Http/GenericResponse.php
@@ -7,6 +7,7 @@ class GenericResponse implements ResponseInterface
public function __construct(
private readonly string $body,
private readonly StatusEnum $status = StatusEnum::OK,
+ private readonly array $headers = [],
)
{
}
@@ -20,4 +21,12 @@ class GenericResponse implements ResponseInterface
{
return $this->body;
}
+
+ /**
+ * @inheritDoc
+ */
+ public function getHeaders(): array
+ {
+ return $this->headers;
+ }
}
\ No newline at end of file
diff --git a/src/Http/GenericRouter.php b/src/Http/GenericRouter.php
index 73ce8f1..b2d8e1d 100644
--- a/src/Http/GenericRouter.php
+++ b/src/Http/GenericRouter.php
@@ -2,9 +2,7 @@
namespace Ardent\Undercurrent\Http;
-use App\Controller\BaseController;
-use Ardent\Undercurrent\Attribute\Route;
-use Ardent\Undercurrent\Collector\ClassAttributeCollector;
+use Ardent\Undercurrent\Container\ClassNotFoundException;
use Ardent\Undercurrent\Container\ContainerInterface;
class GenericRouter implements RouterInterface
@@ -16,6 +14,9 @@ class GenericRouter implements RouterInterface
{
}
+ /**
+ * @throws RouteNotFoundException|ClassNotFoundException
+ */
public function dispatch(RequestInterface $request): ResponseInterface
{
foreach ($this->config->getRoutes() as $route) {
diff --git a/src/Http/ResponseInterface.php b/src/Http/ResponseInterface.php
index abdc290..8047eb9 100644
--- a/src/Http/ResponseInterface.php
+++ b/src/Http/ResponseInterface.php
@@ -7,4 +7,9 @@ interface ResponseInterface
public function getStatus(): StatusEnum;
public function getBody(): string;
+
+ /**
+ * @return array<string>
+ */
+ public function getHeaders(): array;
}
\ No newline at end of file
diff --git a/src/Kernel/BaseKernel.php b/src/Kernel/BaseKernel.php
index 7122dcc..634cafc 100644
--- a/src/Kernel/BaseKernel.php
+++ b/src/Kernel/BaseKernel.php
@@ -33,9 +33,16 @@ class BaseKernel
$_SERVER['REQUEST_URI'],
$_REQUEST,
);
-
$router = $container->get(RouterInterface::class);
- echo $router->dispatch($request)->getBody();
+ $response = $router->dispatch($request);
+
+ http_response_code($response->getStatus()->value);
+
+ foreach ($response->getHeaders() as $header) {
+ header($header);
+ }
+
+ echo $response->getBody();
}
protected function addControllers(ContainerInterface $container, array $controllers): void
|
2023-08-08 17:18:18 +02:00 |
|
|
a55d1c3c2e
|
Properly implement the router with config and interfaces
Expand the container with aliases and argument autowiring
|
2023-08-07 17:51:53 +02:00 |
|
|
e9a636554f
|
Add response and request objects and interfaces
diff --git a/README.md b/README.md
index 4b64da1..c860957 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
Todos:
- [ ] Collect routes properly
- [ ] Process routes correctly
+- [ ] Add request and response objects
diff --git a/app/Controller/BaseController.php b/app/Controller/BaseController.php
index aa0a79b..7df9387 100644
--- a/app/Controller/BaseController.php
+++ b/app/Controller/BaseController.php
@@ -3,12 +3,14 @@
namespace App\Controller;
use Ardent\Undercurrent\Attribute\Route;
+use Ardent\Undercurrent\Http\GenericResponse;
+use Ardent\Undercurrent\Http\ResponseInterface;
class BaseController
{
#[Route('/hello')]
- public function HelloWorld(): string
+ public function HelloWorld(): ResponseInterface
{
- return 'Hello, World!';
+ return new GenericResponse('Hello World!');
}
}
\ No newline at end of file
diff --git a/src/Http/GenericRequest.php b/src/Http/GenericRequest.php
new file mode 100644
index 0000000..c758a40
--- /dev/null
+++ b/src/Http/GenericRequest.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Ardent\Undercurrent\Http;
+
+class GenericRequest implements RequestInterface
+{
+
+ public function __construct(
+ private readonly MethodEnum $method,
+ private readonly string $uri,
+ private readonly array $body,
+ )
+ {
+ }
+
+ public function getMethod(): MethodEnum
+ {
+ return $this->method;
+ }
+
+ public function getUri(): string
+ {
+ return $this->uri;
+ }
+
+ public function getBody(): array
+ {
+ return $this->body;
+ }
+}
\ No newline at end of file
diff --git a/src/Http/GenericResponse.php b/src/Http/GenericResponse.php
new file mode 100644
index 0000000..d80d350
--- /dev/null
+++ b/src/Http/GenericResponse.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Ardent\Undercurrent\Http;
+
+class GenericResponse implements ResponseInterface
+{
+ public function __construct(
+ private readonly string $body,
+ private readonly StatusEnum $status = StatusEnum::OK,
+ )
+ {
+ }
+
+ public function getStatus(): StatusEnum
+ {
+ return $this->status;
+ }
+
+ public function getBody(): string
+ {
+ return $this->body;
+ }
+}
\ No newline at end of file
diff --git a/src/Controller/GenericRouter.php b/src/Http/GenericRouter.php
similarity index 89%
rename from src/Controller/GenericRouter.php
rename to src/Http/GenericRouter.php
index 28f75b1..0332ce5 100644
--- a/src/Controller/GenericRouter.php
+++ b/src/Http/GenericRouter.php
@@ -1,6 +1,6 @@
<?php
-namespace Ardent\Undercurrent\Controller;
+namespace Ardent\Undercurrent\Http;
use App\Controller\BaseController;
use Ardent\Undercurrent\Attribute\Route;
diff --git a/src/Http/MethodEnum.php b/src/Http/MethodEnum.php
new file mode 100644
index 0000000..76948c9
--- /dev/null
+++ b/src/Http/MethodEnum.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace Ardent\Undercurrent\Http;
+
+enum MethodEnum: string
+{
+ case GET = 'GET';
+ case POST = 'POST';
+// case PUT = 'PUT';
+// case PATCH = 'PATCH';
+// case DELETE = 'DELETE';
+// case HEAD = 'HEAD';
+// case OPTIONS = 'OPTIONS';
+// case TRACE = 'TRACE';
+// case CONNECT = 'CONNECT';
+}
diff --git a/src/Http/RequestInterface.php b/src/Http/RequestInterface.php
new file mode 100644
index 0000000..0f564b8
--- /dev/null
+++ b/src/Http/RequestInterface.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace Ardent\Undercurrent\Http;
+
+interface RequestInterface
+{
+ public function getMethod(): MethodEnum;
+
+ public function getUri(): string;
+
+ public function getBody(): array;
+}
\ No newline at end of file
diff --git a/src/Http/ResponseInterface.php b/src/Http/ResponseInterface.php
new file mode 100644
index 0000000..abdc290
--- /dev/null
+++ b/src/Http/ResponseInterface.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Ardent\Undercurrent\Http;
+
+interface ResponseInterface
+{
+ public function getStatus(): StatusEnum;
+
+ public function getBody(): string;
+}
\ No newline at end of file
diff --git a/src/Http/RouterInterface.php b/src/Http/RouterInterface.php
new file mode 100644
index 0000000..186baac
--- /dev/null
+++ b/src/Http/RouterInterface.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Ardent\Undercurrent\Http;
+
+interface RouterInterface
+{
+ public function dispatch(RequestInterface $request): ResponseInterface;
+}
\ No newline at end of file
diff --git a/src/Http/StatusEnum.php b/src/Http/StatusEnum.php
new file mode 100644
index 0000000..6dce100
--- /dev/null
+++ b/src/Http/StatusEnum.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Ardent\Undercurrent\Http;
+
+enum StatusEnum: int
+{
+ case OK = 200;
+ case FORBIDDEN = 403;
+ case NOT_FOUND = 404;
+}
diff --git a/src/Kernel/BaseKernel.php b/src/Kernel/BaseKernel.php
index 6bc8ed5..05ecf06 100644
--- a/src/Kernel/BaseKernel.php
+++ b/src/Kernel/BaseKernel.php
@@ -4,11 +4,12 @@ namespace Ardent\Undercurrent\Kernel;
use App\Controller\BaseController;
use Ardent\Undercurrent\Container\GenericContainer;
-use Ardent\Undercurrent\Controller\GenericRouter;
+use Ardent\Undercurrent\Http\GenericRouter;
+use Ardent\Undercurrent\Http\ResponseInterface;
class BaseKernel
{
- public function __invoke()
+ public function __invoke(): void
{
$container = new GenericContainer();
$container->add(GenericRouter::class);
@@ -23,6 +24,6 @@ class BaseKernel
$route = $router->getRoute($_SERVER['REQUEST_URI']);
$controller = $container->get($route['controller']);
$method = $route['method'];
- echo $controller->$method();
+ echo $controller->$method()->getBody();
}
}
\ No newline at end of file
|
2023-08-07 14:23:00 +02:00 |
|
|
503d8c524a
|
First working version with non working routes
|
2023-07-28 16:14:55 +02:00 |
|