Eliminierung technischer Schulden mit PHPStan, Rector PHP und PHPUnit. Über 20 Jahre Praxiserfahrung in skalierbaren Backends.
- Aktualisiert:
- Autor:
- Roland Golla
Was eine PHPStan Level Strategie ist
Eine PHPStan Level Strategie ist der Plan, mit dem ihr statische Analyse Schritt für Schritt in ein bestehendes PHP Projekt bringt. Ihr startet auf einem Level, das der Code heute schafft, friert alte Fehler in einer Baseline ein und hebt das Level an, sobald das Team bereit ist.
PHPStan kennt elf Level, von 0 als lockerster bis 10 als strengster Prüfung. Jedes höhere Level enthält alle Prüfungen der darunter. Wer Legacy Code direkt auf das höchste Level schickt, bekommt oft tausende Meldungen und gibt auf. Mit einer klaren Strategie wird aus dieser Wand ein Weg, den ihr in kleinen Pull Requests geht. Neuer Code wird ab dem ersten Tag streng geprüft, alter Code wird nach und nach besser.
PHPStan Strategie mit NCA, schnelle Hilfe vom Experten
PHPStan läuft bei uns bei jedem Commit, in unserer eigenen Symfony und Sulu Plattform genauso wie in Kundenprojekten. Wir haben Codebasen von Level 0 bis in die strengen Level begleitet und wissen, an welchen Stellen Teams hängen bleiben: beim Sprung auf Level 5 mit den Argumenttypen, bei Level 8 mit nullable Werten und bei Level 9 und 10 mit mixed. Diese Erfahrung teilen wir seit Jahren in Workshops, Live Sessions und Open Source Beiträgen.
Im PHP Consulting richten wir PHPStan, Baseline und Pipeline in eurem Repository ein. Beim PHP Refactoring arbeiten wir die Baseline gemeinsam mit eurem Team ab. Den Einstieg liefert der PHPStan Bodyscan, die Grundlagen stehen im Glossar zu PHPStan und Psalm. Im NCA RuhrRefactoring Workshop hebt ihr das Level live mit uns an.
Gesetzliche Konformität & Inklusion. Optimierung von Performance und Conversion durch radikal nutzerzentriertes, universelles Design.
Skalierbare KI-Systeme mit echtem Code Ownership. CI/CD, Backup-Strategien und Infrastruktur, die mit deinem Team wächst.
Warum das höchste Level am Anfang falsch ist
Viele Teams installieren PHPStan, stellen level max ein und sehen eine Liste mit tausenden Fehlern. Die Stimmung kippt sofort. Niemand weiß, wo er anfangen soll, und nach zwei Wochen ist PHPStan wieder aus der Pipeline verschwunden.
Das Problem ist nicht das Werkzeug. Das Problem ist der Einstieg. Statische Analyse soll Vertrauen schaffen, und Vertrauen wächst in kleinen Schritten. Ein grüner Lauf auf Level 2 bringt mehr als ein roter Lauf auf Level 10, weil er jeden Tag wirkt und neue Fehler wirklich verhindert.
Die Level bauen aufeinander auf. Level 0 findet unbekannte Klassen und Funktionen. Ab Level 3 prüft PHPStan Rückgabetypen, ab Level 5 die Typen von Argumenten. Level 8 meldet Zugriffe auf Werte, die null sein können, Level 9 und 10 werden beim Typ mixed streng. Jede Stufe macht den Code ein Stück ehrlicher.
Die vier Stufen der PHPStan Einführung
In unseren Projekten läuft die Einführung immer in vier Stufen. Jede Stufe hat ein klares Ziel und ein eigenes Werkzeug. Die Tabelle zeigt die Reihenfolge, die Grafik darunter macht den Weg sichtbar.
PHPStan Level Strategie in vier Stufen
Stufe eins und zwei, Scan und Baseline
Der Bodyscan führt PHPStan für jedes Level einmal aus und zeigt, wie viele Fehler pro Stufe dazukommen. Daran seht ihr, wo die großen Sprünge liegen. Als Startlevel wählt ihr das höchste Level, das sich mit überschaubarem Aufwand auf null bringen lässt, oder ihr startet höher und fangt den Rest mit einer Baseline auf.
Die Baseline ist eine Datei mit allen Fehlern, die heute gemeldet werden. PHPStan überspringt diese Fehler bei den nächsten Läufen. Meldungen kommen nur noch für neuen und geänderten Code. So startet ihr mit einer grünen Pipeline, ohne die Altlasten zu verstecken. Sie stehen sichtbar in einer Datei, die jeder im Team sieht.
composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse --level 5 src tests --generate-baseline
Der Befehl erzeugt die Datei phpstan-baseline.neon mit allen aktuellen Fehlern und der Anzahl pro Datei. Diese Datei bindet ihr in die Konfiguration ein:
includes:
- phpstan-baseline.neon
parameters:
level: 5
paths:
- src
- tests
Verschwindet ein Fehler aus dem Code, meldet PHPStan den nicht mehr passenden Eintrag in der Baseline. Diesen Hinweis solltet ihr eingeschaltet lassen. Er sorgt dafür, dass die Baseline nur kleiner wird und nie heimlich wächst.
Stufe drei, Level für Level hochziehen
Ab jetzt gilt eine einfache Regel: Das Level steigt erst, wenn die Pipeline grün ist und das Team mit den Meldungen umgehen kann. Ein Level pro Sprint ist für viele Teams ein gutes Tempo. Wichtiger als die Geschwindigkeit ist, dass jeder Schritt klein bleibt.
- Level in der phpstan.neon um eins erhöhen
- Analyse laufen lassen und die neuen Meldungen nach Fehlerart sortieren
- Wiederkehrende Muster mit Rector automatisch beheben, den Rest von Hand
- Was in diesem Schritt nicht sinnvoll lösbar ist, in die Baseline aufnehmen
- Kleinen Pull Request erstellen, reviewen, mergen
Parallel arbeitet ihr die Baseline ab. Bewährt hat sich die Pfadfinder Regel: Wer eine Datei anfasst, behebt die Baseline Einträge dieser Datei gleich mit. So schrumpft die Liste dort, wo ohnehin gearbeitet wird, und niemand muss Wochen nur für Altlasten blocken.
Neue Fehler gehören übrigens nicht in die Baseline. Die PHPStan Dokumentation selbst rät dazu, bewusst ignorierte neue Fehler direkt im Code mit einem Kommentar zu markieren. Dort steht dann auch, warum die Meldung ignoriert wird.
Stufe vier, strikt werden und strikt bleiben
Level 10 ist kein Selbstzweck. Es lohnt sich, sobald die Codebasis sauber typisiert ist und das Team die Meldungen versteht. Ab hier helfen drei Ergänzungen:
- Framework Extensions für Symfony und Doctrine, damit PHPStan Container, Repositories und Konfiguration versteht
- phpstan strict rules für Projekte, die besonders defensiv arbeiten wollen
- Bleeding Edge für Teams, die neue Prüfungen früh mitnehmen und große Sprünge beim nächsten Major Update vermeiden wollen
Damit das Niveau hält, gehört PHPStan in die Pipeline und vor jeden Commit. Ein Pre Commit Hook mit GrumPHP fängt Fehler lokal ab, die Pipeline in GitHub Actions oder GitLab CI blockiert den Merge. Wer Type Coverage zusätzlich misst, sieht schwarz auf weiß, wie viel des Codes wirklich typisiert ist.
vendor/bin/phpstan analyse --no-progress --error-format=github
Das GitHub Format zeigt die Meldungen direkt als Anmerkungen im Pull Request. Für GitLab gibt es ein eigenes Format, das die Fehler im Merge Request anzeigt.
Typische Stolperstellen auf dem Weg nach oben
Die Baseline wird zum Mülleimer. Jeder neue Fehler landet per neu generierter Baseline im Schrank. Nach einem Jahr ist sie größer als am Anfang. Regel im Team: Die Baseline darf nur schrumpfen.
Rector läuft blind. Rector nutzt PHPStan, um Typen zu verstehen. Eine riesige Baseline macht auch Rector blind, weil es auf mixed nichts umbauen kann. Die Rector Dokumentation empfiehlt deshalb Level 3 bis 4 ohne Baseline, bevor ihr Rector breit einsetzt.
Level Sprünge ohne Tests. Typen nachzuziehen ändert selten Verhalten, manchmal aber doch. Ein geänderter Rückgabetyp kann einen stillen Fehler sichtbar machen. Unit Tests und Cypress Tests fangen das ab, bevor es Nutzer merken.
KI repariert Meldungen zu großzügig. Ein Coding Agent bringt Fehler schnell auf null, gern mit Kommentaren zum Ignorieren oder mit breiten Typen wie mixed. Das sieht grün aus, macht den Code aber nicht sicherer. Jeder Fix gehört in ein Review.
The different levels from 0 to 10 allow you to gradually tighten the analysis
PHPStan Bodyscan
Optimiere deinen PHP-Code mit PHPStan Bodyscan. Finde das beste Level, schätze den Aufwand und decke Schwachstellen auf. Teste jetzt die Codequalität - kostenfrei! Lerne die besten Tipps in unseren YouTube Coding-Tutorials.
Mehr erfahrenDie NCA Erfahrung mit statischer Analyse
Statische Analyse ist bei uns kein Projekt, sondern Alltag. Sie läuft in jeder Pipeline und vor jedem Commit. Die Werkzeuge rund um PHPStan findet ihr im Glossar.
Neben PHPStan setzen wir Psalm für zusätzliche Typprüfung ein. Den Startpunkt liefert der PHPStan Bodyscan, den Typisierungsgrad misst Type Coverage. Automatische Umbauten übernimmt Rector PHP, das wie PHPStan auf dem Abstract Syntax Tree arbeitet. Toten Code finden Class Leak und Unused Public. Vor jedem Commit prüft GrumPHP, den Code Stil halten Easy Coding Standard und der PHP Coding Standards Fixer sauber. Für Laravel Projekte gibt es Larastan. Was die Tests abdecken, zeigt PHPUnit mit Code Coverage.
Erreichen Sie unsere PHP Consultant Spezialisten
Wir sind Experten für PHP und helfen Ihnen, Ihre digitalen Herausforderungen zu meistern. Unser erfahrenes Team unterstützt Sie bei PHP Updates, PHP Refactoring und berät Sie remote zu allen Fragen rund um PHP. Mit unseren vollautomatischen CI/CD Deployments und einer robusten Docker-Infrastruktur bringen wir Ihre PHP-Projekte auf das nächste Level. Vertrauen Sie auf unsere Expertise für zuverlässige und skalierbare PHP-Lösungen.
Häufige Fragen zu PHPStan Level und Baseline
Die Fragen, die Teams beim Einführen von PHPStan in bestehende Projekte am häufigsten stellen.
Mit dem höchsten Level, das sich mit überschaubarem Aufwand auf null Fehler bringen lässt. Ein Bodyscan zeigt die Fehlerzahl pro Level und damit die großen Sprünge. Alternativ startet ihr höher und fangt den Rest mit einer Baseline auf. Wichtig ist eine grüne Pipeline ab dem ersten Tag.
PHPStan kennt elf Level, von 0 bis 10. Level 0 prüft Grundlagen wie unbekannte Klassen und Funktionen, Level 10 ist beim Typ mixed besonders streng. Die Level sind kumulativ, jedes höhere Level enthält alle Prüfungen der darunter. Mit level max nutzt ihr immer das aktuell höchste Level.
Ja, für bestehenden Code. Die Baseline friert alte Fehler ein, damit ihr sofort mit strengen Regeln für neuen Code starten könnt. Entscheidend ist, dass sie nur schrumpft. Neue Fehler gehören nicht hinein, sondern werden behoben oder mit begründetem Kommentar direkt im Code markiert.
So schnell, wie die Pipeline grün bleibt und das Team mitkommt. Ein Level pro Sprint ist für viele Projekte ein gutes Tempo. Kleine Pull Requests pro Level lassen sich am selben Tag reviewen. Große Sprünge über mehrere Level erzeugen dagegen Frust und unübersichtliche Änderungen.
Teilweise. Coding Agents bringen Meldungen schnell auf null, greifen dabei aber gern zu Ignore Kommentaren oder zu breiten Typen wie mixed. Das sieht grün aus, verbessert den Code aber kaum. Wiederkehrende Muster löst Rector deterministisch, alle anderen Änderungen gehören in ein menschliches Review.
Die Baseline ist eine automatisch erzeugte Liste aller aktuellen Fehler mit Anzahl pro Datei. ignoreErrors in der Konfiguration ist für gezielte, dauerhafte Ausnahmen gedacht. Für einzelne bewusste Ausnahmen ist ein Kommentar direkt an der Zeile am besten, weil dort auch die Begründung steht.
Meist reicht ein Werkzeug. PHPStan hat ein großes Ökosystem an Extensions für Symfony, Doctrine und Laravel. Psalm ergänzt bei Bedarf weitere Typprüfungen. Zwei Werkzeuge mit unterschiedlichen Regeln können sich aber widersprechen. Wichtiger als die Wahl ist, dass statische Analyse überhaupt in der Pipeline läuft.
Die Symfony Extension versteht den Service Container und die Konfiguration, die Doctrine Extension die Repositories und Entities. Ohne diese Extensions meldet PHPStan viele Fehler, die keine sind. Für PHPUnit Tests gibt es eine eigene Extension, die Mocks und Assertions richtig einordnet.
Rector nutzt PHPStan, um Typen zu verstehen. Was PHPStan nicht erkennt, kann Rector nicht sicher umbauen. Eine große Baseline mit vielen Typfehlern macht Rector deshalb blind. Die Rector Dokumentation empfiehlt Level 3 bis 4 ohne Baseline, bevor Rector breit eingesetzt wird.
Als eigenen Job in GitHub Actions oder GitLab CI, der bei Fehlern den Merge blockiert. Mit dem passenden Error Format erscheinen die Meldungen direkt im Pull Request oder Merge Request. Lokal fängt ein Pre Commit Hook mit GrumPHP Fehler ab, bevor sie überhaupt gepusht werden.
Die neuen Meldungen in die Baseline aufnehmen und sofort auf die neue Version wechseln. So prüft der neue Analyser euren neuen Code direkt strenger, während die alten Funde in Ruhe abgearbeitet werden. Bleeding Edge hilft, solche Sprünge beim nächsten Major Update kleiner zu halten.
Wir richten PHPStan mit Baseline, Extensions und Pipeline direkt in eurem Repository ein und heben das Level gemeinsam mit dem Team an. Am Anfang steht ein kostenloses Kennenlernen mit Blick in den Code. Danach schätzen wir den Aufwand und rechnen transparent nach Minuten ab.