Michael Korte – Senior Full-Stack Developer Freelancer aus Dortmund

Ziel dieses Teils

Viele Systeme behandeln Fehlerseiten als Ausnahme: andere Templates, andere Logik, andere Pfade.

Clean-Output-MVC verfolgt einen anderen Ansatz: Fehler sind reguläre Requests mit einem definierten Ergebnis.

Merksatz

404 ist kein Sonderfall – sondern ein normaler Seitenzustand.

10.1 Fehler entstehen im Routing – nicht im Rendering

Der Router beantwortet nur eine Frage: Gibt es eine passende Route?

  • Ja → passender Controller
  • Nein → Fallback-Controller
// stark vereinfacht
if (!$routeMatched) {
    return $errorController->notFound();
}

Wichtig: Der Router erzeugt kein HTML und entscheidet nicht über Darstellung.

10.2 Der ErrorController

Fehlerseiten sind normale Controller-Antworten. Sie liefern – wie jede andere Seite – einen PageContext.

<?php

namespace App\Controller;

use Core\PageContext;

final class ErrorController
{
    public function notFound(): PageContext
    {
        return (new PageContext())
            ->withStatus(404)
            ->withMeta([
                'title' => 'Seite nicht gefunden',
            ])
            ->withBlocks([
                [
                    'type' => 'text',
                    'data' => [
                        'title'   => '404 – Nicht gefunden',
                        'content' => '<p>Die angeforderte Seite existiert nicht.</p>',
                    ],
                ],
            ]);
    }
}

Kein Sonder-Template. Keine Sonder-Pipeline. Der gleiche Weg wie bei jeder anderen Seite.

10.3 Statuscodes sind Teil des PageContext

HTTP-Statuscodes gehören nicht „nebenbei“ gesetzt, sondern sind Teil des Seitenzustands.

$page
  ->withStatus(404)
  ->withMeta([...])
  ->withBlocks([...]);
  • Status beeinflusst die Response
  • Status beeinflusst SEO & Caching
  • Templates müssen den Status nicht kennen

Der Renderer setzt den Status genau einmal – zentral und nachvollziehbar.

10.4 Warum das konzeptionell wichtig ist

  • Fehlerseiten sind SEO-korrekt
  • Design & Struktur bleiben konsistent
  • Kein versteckter Sondercode
  • Monitoring & Logging werden einfacher

Wichtig

Das System „scheitert“ nicht unkontrolliert – es liefert einen bewusst gestalteten Fehlerzustand.

Zwischenfazit

Mit diesem Teil ist der Request-Lifecycle vollständig:

  • Routing entscheidet
  • Controller beschreiben Zustand
  • PageContext trägt Status & Inhalt
  • Renderer erzeugt den Output

Fehler sind dabei kein Bruch, sondern ein normaler, erklärbarer Pfad.

Projekt & Quellcode

Der Bootstrap und der Einstiegspunkt sind im Repository vollständig nachvollziehbar umgesetzt: