Ziel dieses Teils
Zum ersten Mal erzeugt das System jetzt echtes HTML. Wichtig ist dabei nicht das Template selbst, sondern wo es benutzt wird.
Grundregel
Controller liefern Zustand – Templates liefern Darstellung.
Sie kennen sich nicht gegenseitig.
7.1 Zielstruktur
/project-root
├─ public/
│ └─ index.php
├─ src/
│ ├─ Core/
│ │ ├─ App.php
│ │ ├─ Router.php
│ │ ├─ Renderer.php
│ │ ├─ View.php
│ │ └─ PageContext.php
│ └─ App/
│ └─ Controller/
│ └─ HomeController.php
├─ templates/
│ ├─ base.html.twig
│ └─ home.html.twig
└─ vendor/
Templates liegen bewusst außerhalb von App und Core. Der Core kennt nur einen Renderer – nicht die Seitenlogik.
7.2 View: reine Template-Engine
<?php
namespace Core;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
final class View
{
private Environment $twig;
public function __construct()
{
$loader = new FilesystemLoader(
dirname(__DIR__, 2) . '/templates'
);
$this->twig = new Environment($loader, [
'cache' => false,
'autoescape' => 'html',
]);
}
public function render(string $template, array $data): string
{
return $this->twig->render($template, $data);
}
}
Wichtig
Die View ist kein Service für Controller.
Sie wird ausschließlich vom Renderer benutzt.
7.3 Base-Layout
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>{{ title|default('Clean Output MVC') }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<header>
<h1>Clean-Output-MVC</h1>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<small>Tutorial v0.1</small>
</footer>
</body>
</html>
7.4 Seiten-Template
{% extends "base.html.twig" %}
{% block content %}
<h2>{{ headline }}</h2>
<p>{{ message }}</p>
{% endblock %}
7.5 Controller: kein Rendering
<?php
namespace App\Controller;
use Core\PageContext;
final class HomeController
{
public function index(): PageContext
{
$page = new PageContext();
$page
->withTemplate('home.html.twig')
->withData([
'headline' => 'Hello Twig',
'message' => 'Die erste echte Ausgabe entsteht im Renderer.'
]);
return $page;
}
}
Entscheidender Punkt
Der Controller kennt kein Twig.
Er beschreibt nur den Seitenzustand.
Zwischenfazit
- HTML entsteht ausschließlich im Renderer
- Templates sind reine Darstellung
- Controller bleiben testbar und deterministisch
Jetzt greift das Konzept
Wenn sich HTML ändert, suchst du im Template.
Wenn sich Inhalt ändert, suchst du im PageContext.
Wenn sich Entscheidungen ändern, suchst du im Controller.
Projekt & Quellcode
Der Bootstrap und der Einstiegspunkt sind im Repository vollständig nachvollziehbar umgesetzt:
- 👤 GitHub-Profil: github.com/MichaelKorte73
- 📦 Projekt-Repository: github.com/MichaelKorte73/CleanOutputMVC