Ziel dieses Teils
In diesem Abschnitt entsteht zum ersten Mal etwas, das sich für Außenstehende wie eine „Seite“ anfühlt.
Technisch tun wir aber nur eines: Wir treffen eine Entscheidung auf Basis der URL.
- Router registrieren
- erste Route definieren
- Controller als Ziel
- Error-Controller als Standardweg
5.1 Routing ist keine Darstellung
Der Router beantwortet genau eine Frage:
Welche Entscheidung wird getroffen?
Welcher Controller ist zuständig?
Nicht: welche Seite, nicht: welches Template.
Alles andere passiert später.
5.2 Router registrieren (Bootstrap)
Der Router wird explizit im Bootstrap vorbereitet.
<?php
// App/Bootstrap.php
use Core\\Router;
use App\\Controller\\HomeController;
use App\\Controller\\ErrorController;
private static function register(App $app): void
{
$router = new Router();
$router->get('/', [HomeController::class, 'index']);
// kein Match → ErrorController
$router->fallback([ErrorController::class, 'error404']);
$app->setRouter($router);
}
Wichtig: Der Fallback ist kein Sonderfall, sondern der normale Weg, wenn keine Route passt.
5.3 Der erste Controller
Controller sind Entscheidungsinstanzen. Sie erzeugen noch kein HTML.
<?php
namespace App\\Controller;
use Core\\PageContext;
final class HomeController
{
public function index(): PageContext
{
$page = new PageContext();
$page->withData([
'message' => 'Hallo Welt'
]);
return $page;
}
}
Wichtige Beobachtung
Der Controller gibt keinen String zurück,
sondern einen PageContext.
5.4 ErrorController als normaler Controller
Fehlerseiten sind keine Sonderlogik, sondern reguläre Controller-Ziele.
<?php
namespace App\\Controller;
use Core\\PageContext;
final class ErrorController
{
public function error404(): PageContext
{
$page = new PageContext();
$page
->withStatus(404)
->withData([
'title' => 'Seite nicht gefunden'
]);
return $page;
}
}
Der Router entscheidet, dass es ein Fehler ist – der Controller entscheidet, wie damit umgegangen wird.
5.5 Warum hier noch nichts gerendert wird
Auch jetzt haben wir noch:
- kein Template
- kein HTML
- keine Assets
Das ist Absicht.
Der Controller beschreibt nur den Seitenzustand.
Trennung greifbar
Entscheidung ≠ Darstellung
Zustand ≠ Ausgabe
Übergang zu Teil 6
Jetzt existiert erstmals ein vollständiger Ablauf:
- Request
- Router
- Controller
- PageContext
In Teil 6 folgt der entscheidende Schritt: Rendering – und warum nur der Renderer HTML erzeugt.