refactor: Umstellung auf Mini-MVC-Architektur (Issue #46)
All checks were successful
Deploy Feature Branch to Test / deploy (push) Successful in 24s

- Front Controller Pattern mit public/index.php als Einstiegspunkt
- Eigenes Routing (App\Core\Router) ohne externes Framework
- Controller: HomeController, ImpressumController, DatenschutzController
- Views mit gemeinsamem Layout (app/views/layouts/main.php)
- PSR-4 Autoloading
- Statische Assets nach public/ verschoben
- Alte Dateien (index.php, impressum.html, datenschutz.html) geloescht
- 301-Redirects fuer alte URLs
- PHP 8.5 kompatibel
- Apache DocumentRoot auf public/ gesetzt
This commit is contained in:
2026-05-19 14:38:38 +00:00
parent 73635a5f03
commit 1aedcaf314
130 changed files with 1303 additions and 1179 deletions

60
app/core/Router.php Normal file
View File

@@ -0,0 +1,60 @@
<?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();
}
}

46
app/core/View.php Normal file
View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace App\Core;
class View
{
private string $viewsPath;
private array $data = [];
public function __construct(?string $viewsPath = null)
{
$this->viewsPath = $viewsPath ?? dirname(__DIR__) . '/views';
}
public function assign(string $key, mixed $value): void
{
$this->data[$key] = $value;
}
public function render(string $view, string $layout = 'main'): void
{
$viewFile = $this->viewsPath . '/' . $view . '.php';
$layoutFile = $this->viewsPath . '/layouts/' . $layout . '.php';
if (!file_exists($viewFile)) {
throw new \RuntimeException("View {$view} nicht gefunden: {$viewFile}");
}
if (!file_exists($layoutFile)) {
throw new \RuntimeException("Layout {$layout} nicht gefunden: {$layoutFile}");
}
// Extract data to variables for the view
extract($this->data, EXTR_SKIP);
// Capture view content
ob_start();
require $viewFile;
$content = ob_get_clean();
// Render layout with $content
require $layoutFile;
}
}