All checks were successful
Deploy Feature Branch to Test / deploy (push) Successful in 28s
Lint / PHP Syntax Check (push) Successful in 36s
Lint / CSS Lint (stylelint) (push) Successful in 1m18s
Lint / HTML Lint (htmlhint) (push) Successful in 1m11s
Lint / PHP Syntax Check (pull_request) Successful in 37s
Lint / CSS Lint (stylelint) (pull_request) Successful in 1m20s
Lint / HTML Lint (htmlhint) (pull_request) Successful in 1m13s
- Add composer.json with PHPUnit 11 and PSR-4 autoloading - Add phpunit.xml configuration - Rename app/core/ → app/Core/ and app/controllers/ → app/Controllers/ (PSR-4) - Add 18 unit tests for App\Core\Router (31 assertions) - addRoute(): default action, custom action, overwrite - dispatch(): URL normalization, direct match, legacy redirects - dispatch(): 404 handling, controller/action not found exceptions - TestableRouter subclass to intercept side-effects - Update .gitignore (vendor/, .phpunit.cache/)
61 lines
1.6 KiB
PHP
61 lines
1.6 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Core;
|
||
|
||
class Router
|
||
{
|
||
private array $routes = [];
|
||
|
||
public function addRoute(string $path, string $controller, string $action = 'index'): void
|
||
{
|
||
$this->routes[$path] = [
|
||
'controller' => $controller,
|
||
'action' => $action,
|
||
];
|
||
}
|
||
|
||
public function dispatch(string $uri): void
|
||
{
|
||
// Normalize: strip query string and trailing slash
|
||
$path = parse_url($uri, PHP_URL_PATH);
|
||
$path = rtrim($path, '/') ?: '/';
|
||
|
||
// Direct match
|
||
if (isset($this->routes[$path])) {
|
||
$this->execute($this->routes[$path]);
|
||
return;
|
||
}
|
||
|
||
// Legacy .html redirect (301)
|
||
if (preg_match('#^/(impressum|datenschutz)\.html$#', $path, $m)) {
|
||
header('Location: /' . $m[1], true, 301);
|
||
exit;
|
||
}
|
||
|
||
// 404
|
||
http_response_code(404);
|
||
echo '<h1>404 – Seite nicht gefunden</h1>';
|
||
echo '<p><a href="/">Zurück zur Startseite</a></p>';
|
||
}
|
||
|
||
private function execute(array $route): void
|
||
{
|
||
$controllerClass = $route['controller'];
|
||
$action = $route['action'];
|
||
|
||
if (!class_exists($controllerClass)) {
|
||
throw new \RuntimeException("Controller {$controllerClass} nicht gefunden.");
|
||
}
|
||
|
||
$controller = new $controllerClass();
|
||
|
||
if (!method_exists($controller, $action)) {
|
||
throw new \RuntimeException("Action {$action} in {$controllerClass} nicht gefunden.");
|
||
}
|
||
|
||
$controller->$action();
|
||
}
|
||
}
|