# Code-Strategie: Custom-Code verbessern und migrationsfreundlich halten

Diese Empfehlung beschreibt, wie der Custom-Code laufend besser wird und
zugleich eine mögliche spätere Laravel-Migration begünstigt — ohne die
Migration jetzt durchzuführen.

Hintergrund: Vorerst bleibt es bei Custom-Code (der frühere Programmierer
übernimmt eventuell wieder). Erst bei klarer Absage wird eine Migration mit dem
Kunden überlegt.

> **Umsetzungsstand** (siehe `CHANGELOG.md`): Der Stufenplan ist zu weiten Teilen
> abgearbeitet. **Erledigt:** die gestaffelte Reihenfolge bis Stufe 2 — Datenzugriff
> vollständig hinter Repositories (P1, `app/Repository/`, alle Fachobjekte inkl. der
> sechs Lookups), Konfiguration zentralisiert (P3, `.env`/`config()`), PSR-4/`App\`
> (P5), Golden-Master ausgebaut plus erster Unit-Test (`tests/csrf_test.php`, P7).
> **Noch offen:** Darstellung von Logik trennen / Views statt HTML-in-PHP (P2,
> Stufe 3 — `detail/function.php` erzeugt weiterhin `echo "<option>…"`), Front-
> Controller-Zerlegung von `header.php` (P4) und gekapseltes Input-Handling (P6,
> Stufe 4). Die folgenden Maßnahmen-Beschreibungen bleiben als Begründung stehen.

## Geht das überhaupt? — Ja, ohne Doppelarbeit

Die Entscheidung „jetzt kein Laravel" und das Ziel „migrationsfreundlich
werden" widersprechen sich nicht. Ein Framework wie Laravel ist im Kern nichts
anderes als eine saubere Ausprägung von Prinzipien, die man auch framework-los
umsetzen kann: zentraler Einstiegspunkt, Trennung von HTTP/Logik/Datenzugriff/
Darstellung, Konfiguration außerhalb des Codes, Autoloading über Namespaces,
Tests als Sicherheitsnetz.

Der teure Teil einer Migration ist **nicht** das Umschreiben auf
Framework-Syntax, sondern das Entwirren von vermischtem HTML/SQL/Logik und das
Nachvollziehen impliziter Annahmen (globaler `$db`, host-basierte Konfiguration,
Session-Logik im Header). Genau diese Entwirrung macht den Custom-Code **heute
schon** wartbarer. Man arbeitet also einmal in die richtige Richtung.

Die aktuelle Trajektorie ist bereits richtig: `bootstrap.php` (Autoloader +
`env()`), `db_query()` als Datenzugriffs-Keimzelle, der Golden-Master-Test.
Bedingung: framework-neutrale Abstraktionen wählen, keine „Eigenerfindungen",
die man später wegwirft.

## Maßnahmen (priorisiert)

### P1 — Datenzugriff hinter Repositories bündeln

Die verstreuten `mysqli_query`-Aufrufe schrittweise auf `db_query()` umstellen
und dann pro Fachobjekt zu Repository-Klassen zusammenführen
(`ProjektRepository`, `DokumentRepository`, `TerminRepository`,
`UserRepository`). Jede Methode kapselt genau ein SQL (`findById($id)`,
`insert(array $data)`, `listForKanton($kantonId)`).

- **Wartbarkeit:** SQL liegt an einer benennbaren, testbaren Stelle statt
  verstreut in HTML-Dateien. Beseitigt zugleich den Rest der SQLi-Fläche.
- **Migration:** Die Methodennamen bilden sich fast 1:1 auf Eloquent-Models/
  Query-Builder ab. Die Migration wird zu „Innenleben austauschen" statt
  „hunderte Call-Sites finden". Wichtigster Hebel.
- Hinweis: `db_query()` bindet aktuell alles als String. An der
  Repository-Grenze IDs konsequent `(int)`-casten, damit die Datensemantik
  sauber ist (das erbt Eloquent später als Attribut-Casts).

### P2 — Darstellung von Logik trennen (Richtung Templating → Blade)

Die HTML-erzeugenden Funktionen (z. B. `aktionListSelected`,
`kategorieListSelected` in `detail/function.php`, die `echo "<option>…"`) sind
das migrationsfeindlichste Muster. Datenbeschaffung an den Dateianfang bzw. ins
Repository, HTML in reine PHP-Templates (Views), die nur noch Variablen ausgeben.

- **Wartbarkeit:** HTML-Änderungen ohne Logik-Nebenwirkungen; Wiederverwendung
  von Bausteinen (Navbar, Dropdowns, Termine-Sidebar).
- **Migration:** Reine PHP-Templates mit `<?= $var ?>` lassen sich mechanisch
  nach Blade übersetzen (`{{ $var }}`). HTML-in-PHP-Funktionen müssten komplett
  neu geschrieben werden.

### P3 — Konfiguration zentralisieren

Die host-basierte Konstanten-Auswahl ist dupliziert in `db.php` UND `header.php`.
In eine einzige Stelle ziehen (`config()`-Zugriff, gespeist aus `.env` + einem
Config-Array je Umgebung). `$SUPERUSERS`, `$UPLOAD_DIR`, `$BASE_URL` etc. über
`config('...')` statt globaler Variablen.

- **Wartbarkeit:** Eine Quelle der Wahrheit; kein Auseinanderlaufen.
- **Migration:** Laravel hat exakt dieses Modell (`config/*.php` + `.env`); der
  `env()`-Helper ist bereits Laravel-nah.

### P4 — Front-Controller / Bootstrap-Aspekte trennen

`header.php` macht implizit Kernel-Arbeit (Session, Auth-Guard, Maintenance,
Konfiguration, DB). In klar benannte Bausteine zerlegen. Bewusst leichtgewichtig
— keinen ambitionierten eigenen Router bauen.

- **Wartbarkeit:** Auth-/Session-Logik an einer Stelle nachvollziehbar/testbar.
- **Migration:** Diese Bausteine werden in Laravel zu Middleware (Maintenance
  ist sogar eingebaut).

### P5 — PSR-4 / Namespaces / Autoloading

Composer ist da (nur phpdotenv). Einen `App\`-Namespace mit PSR-4 in
`composer.json` eintragen und neue Klassen dort ablegen. Bestehende prozedurale
Dateien bleiben vorerst; die neue Struktur wächst daneben.

- **Wartbarkeit:** kein manuelles `require`; klare Verortung.
- **Migration:** Laravel ist PSR-4/`App\` — Klassen wandern per Verschieben.

### P6 — Request-/Input-Handling und Validierung kapseln

Direkte `$_POST`/`$_GET`-Zugriffe hinter kleine Helper legen (`input('feld')`,
`input_int('p')`) und Pflichtfeld-/Typ-Prüfungen bündeln.

- **Wartbarkeit:** einheitliches Defaulting, weniger `Undefined index`,
  Validierung an einer Stelle.
- **Migration:** entspricht Laravels `Request`/Form-Request-Validierung.

### P7 — Tests als Migrations-Sicherheitsnetz

Der Golden-Master (`tests/`) ist goldrichtig. Ausbauen: mehr URLs, mittelfristig
Unit-Tests (PHPUnit) für die neuen Repositories.

- **Migration (höchster doppelter Nutzen):** Der Golden-Master vergleicht die
  HTML-Ausgabe **unabhängig von der Implementierung** — dieselben Snapshots kann
  man nach einer Migration erneut laufen lassen, um unverändertes Verhalten zu
  beweisen. Hier investierter Aufwand ist nie verloren.

## Was vermeiden (erschwert Migration)

- Kein neues `global $db` / direktes `mysqli_query` — nur über `db_query()`/
  Repository.
- Kein neues HTML-aus-PHP-Funktionen (teuerster Migrationsposten).
- Keine framework-fremden Eigenlösungen mit eigener Philosophie (selbstgebauter
  „cleverer" ORM, eigenes Routing-DSL, eigenes Event-/DI-Framework).
- Keine tiefe Kopplung an mysqli-Spezifika in der Fachlogik — in Repositories
  kapseln.
- Die host-basierte Config-Logik nicht weiter ausbauen, sondern zusammenführen.

## Aufwand klug investieren

**Doppelter Nutzen (jetzt UND bei Migration):** Repository-Schicht (P1), reine
Templates (P2), Config (P3), PSR-4 (P5), Tests (P7), zentrale Input-Zugriffe
(P6).

**Grenzfall:** selbstgebauter Front-Controller (P4) — die *Zerlegung* der
Aspekte trägt (→ Middleware), ein eigener Router wird ersetzt. Minimalinvasiv
bleiben.

**Eher Wegwerf (nur für Custom, nur so viel wie nötig):** Feinschliff an der
`mysqli`-Mechanik von `db_query()` selbst; Kosmetik am Bootstrap-4-Markup
(Frontend-Modernisierung ist ein eigenes, unabhängiges Thema; die Bibliotheken
sind inzwischen lokalisiert, kein CDN mehr — siehe `docs/frontend-abhaengigkeiten.md`).

> Faustregel: **Aufwand fließt in Struktur und Grenzen (Schnittstellen zwischen
> Schichten), nicht in Mechanik dahinter.** Die Mechanik darf „hässlich mysqli"
> bleiben, solange sie hinter einer sauberen Repository-Methode versteckt ist.

## Gestaffelte Reihenfolge (parallel zur SQLi-Härtung)

Der laufende `db_query`-Rollout ist der ideale Träger — er zwingt ohnehin, jede
Query-Stelle anzufassen.

- **Stufe 0:** SQLi-Rollout fortsetzen. Regel: beim Anfassen einer Datei die
  Query gleich in die passende Repository-Methode heben. Golden-Master nach
  jeder Datei.
- **Stufe 1 (Fundament):** PSR-4/`App\` in `composer.json` (P5); Config-
  Duplikation zusammenführen, `config()` neben `env()` (P3).
- **Stufe 2 (Kern):** Repositories anlegen, beginnend mit **Projekt** (durch
  Golden-Master-URLs gut abgedeckt) (P1).
- **Stufe 3:** HTML-Funktionen in `detail/function.php` zu Views umbauen, dann
  die großen Seiten (P2).
- **Stufe 4:** Input-Zugriffe kapseln (P6); Auth/Session/Maintenance aus
  `header.php` zerlegen (P4).
- **Querschnitt:** `tests/urls.txt` erweitern; nach Stufe 2 erste
  PHPUnit-Tests (P7).

Nach jeder Stufe gibt es sofort Wartbarkeitsgewinn, und die Codebasis-Grenzen
verlaufen zunehmend wie in Laravel. Kommt die Migration, wird sie zu einem
testgesicherten „Innenleben austauschen"; kommt sie nicht, hat man trotzdem
deutlich besseren Custom-Code. Keine der Maßnahmen P1–P3/P5–P7 ist verloren.
