Mein Platz in der WordPress-Community
- Mein wordpress.org-Konto besteht seit 2006.
- Ich habe zum WordPress-Core in den Versionen 7.0 und 7.1 beigetragen.
- Ich betreue 30 Plugins auf wordpress.org.
- Ich organisiere WordCamps und trete dort als Speaker auf.
- Ich war bei jedem WordCamp Europe von 2017 bis 2026 dabei.
Ich bin Mariusz Szatkowski und entwickle PHP-Anwendungen allein, von Gdynia in Polen aus. Ein Büro in Bielefeld gibt es nicht, ich arbeite remote und schriftlich, ohne Termine und ohne Telefonate. Den Code schreibe ich selbst.
Diese Seite handelt von einer Aufgabe, die in vielen Firmen irgendwann ansteht: Eine PHP-Anwendung läuft seit Jahren, der Entwickler ist weg, Tests gibt es nicht, und trotzdem soll sie weiterentwickelt oder auf eine neuere PHP-Version gebracht werden. Hier steht, in welcher Reihenfolge ich dabei vorgehe und was Sie davon prüfen können, auch wenn Sie nie mit mir arbeiten.
Warum ich nicht zuerst aufräume
Der Reflex bei fremdem Altcode ist aufräumen. Ohne Tests ist das riskant, denn niemand kann belegen, dass die Anwendung nach dem Aufräumen dasselbe tut wie davor. Deshalb gilt bei mir eine feste Reihenfolge, und sie läuft immer auf einer Kopie, nie auf der Produktion:
- Bestandsaufnahme. Ich lese
composer.json, die Verzeichnisstruktur und die Stellen, an denen Geld, Kundendaten oder Schnittstellen bewegt werden. - Charakterisierungstests mit PHPUnit. Sie halten fest, was der Code heute liefert.
- PHPStan mit Baseline. Die statische Analyse läuft ab dem ersten Tag, ohne dass vorher alles behoben sein muss.
- Stufen anheben. Eine Stufe, Fehler beheben, in den Hauptzweig, dann die nächste.
- Rector in kleinen Schritten. Automatische Umbauten, jeder als eigener Pull Request.
- Erst dann neue Funktionen. Sie landen auf einem Stand, der geprüft ist.
Charakterisierungstests: festhalten, was der Code tut
Ein Charakterisierungstest prüft nicht, was die Funktion tun sollte, sondern was sie tut. Ich rufe den vorhandenen Code mit echten Eingaben auf, schreibe die Ausgabe als erwarteten Wert in den Test und halte so den Ist-Zustand fest. Liefert eine Funktion ein Ergebnis, das nach einem Fehler aussieht, kommt es trotzdem in den Test, mit einem Kommentar und einem Eintrag in meiner schriftlichen Liste. Ob es ein Fehler ist, entscheiden Sie als Fachseite, nicht ich beim Aufräumen.
Das Grundmuster steht in der PHPUnit-Dokumentation: Die Tests für eine Klasse stehen in einer Testklasse, die von PHPUnit\Framework\TestCase erbt, die Testmethoden sind öffentliche Methoden mit dem Präfix test, und assertSame() vergleicht Ist und Soll. Ein Beispiel für eine Funktion aus einem Altsystem, der Name ist erfunden:
<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
require_once __DIR__ . '/../legacy/rabatt.php';
final class RabattTest extends TestCase
{
public function testLiefertHeuteDenWertDesAltsystems(): void
{
// Erwartungswert: Ausgabe des unveränderten Altcodes, nicht eine Annahme.
$this->assertSame('87.50', berechne_rabatt(250.0, 'A'));
}
}Der Wert 87.50 stammt in der Praxis aus einem Lauf des alten Codes mit einem echten Auftrag aus Ihrem Bestand. Ich suche die Eingaben dort, wo Fehler teuer wären: Rechnungsbeträge, Steuersätze, Rabattstaffeln, Importe, Exporte. Eine lückenlose Abdeckung ist nicht das Ziel. Das Ziel ist, dass die Pfade, die ich als Nächstes anfasse, abgesichert sind.
Echtdaten auf der Kopie: was Datenschutz hier verlangt
Gute Charakterisierungstests brauchen realistische Eingaben, und realistische Eingaben enthalten oft Namen, Adressen oder Bestellungen. Für Unternehmen in Bielefeld ist die Aufsichtsbehörde die LDI NRW. Auf ihrer Seite Datenschutz im KMU stellt sie Mustervorlagen und Hinweise zusammen, unter anderem zu Auftragsverarbeitung und zu technischen und organisatorischen Maßnahmen (TOM).
Die Rechtsgrundlage lese ich in der DSGVO:
- Art. 28 Abs. 1: Wird im Auftrag eines Verantwortlichen verarbeitet, arbeitet dieser nur mit Auftragsverarbeitern, die hinreichend Garantien für geeignete technische und organisatorische Maßnahmen bieten. Art. 28 Abs. 3 verlangt dafür einen Vertrag.
- Art. 32 Abs. 1 Buchstabe a: Zu den geeigneten Maßnahmen zählen unter anderem die Pseudonymisierung und Verschlüsselung personenbezogener Daten.
- Art. 25 Abs. 1: Pseudonymisierung steht dort als Beispiel für eine Maßnahme, die den Grundsatz der Datenminimierung wirksam umsetzt.
Für die Arbeit heißt das: Ich bitte Sie bevorzugt um eine Kopie mit pseudonymisierten oder erfundenen Daten. Wenn ohne Echtdaten kein sinnvoller Test möglich ist, schließen wir vorher einen Auftragsverarbeitungsvertrag. Eine Kopie mit Echtdaten verlässt Ihre Umgebung nicht ohne Ihre ausdrückliche schriftliche Freigabe, und ich lösche sie nach dem Abschluss.
Wer die Anwendung danach weiterführt
Mein Ziel ist eine Übergabe, nach der die Anwendung ohne mich weiterläuft. Die Tests, die PHPStan-Konfiguration und die Rector-Konfiguration liegen dazu in Ihrem Repository, und jeder Entwickler, der später dazukommt, kann sie lesen und ausführen. Die Universität Bielefeld nennt auf ihrer Profilseite 1969 als Gründungsjahr, rund 24.500 Studierende und 14 Fakultäten, darunter eine Technische Fakultät. Die Hochschule Bielefeld führt unter ihren Fachbereichen die Ingenieurwissenschaften und Mathematik. Ob Ihr nächster interner Entwickler von dort kommt, weiß ich nicht. Sicher ist nur: Wer eine Anwendung mit Tests und statischer Analyse übernimmt, braucht für den Einstieg weniger Erklärung als bei einer Anwendung ohne beides.

Foto: Ub12vow, CC BY-SA 3.0, Wikimedia Commons.
PHPStan: Stufen und Baseline
PHPStan erklärt in der Dokumentation zu den Regelstufen, dass es 11 Stufen gibt, von 0 (am lockersten) bis 10 (am strengsten), und dass sie kumulativ sind: Stufe 5 enthält alle Prüfungen der Stufen 0 bis 4. Grob gesagt prüfen die unteren Stufen Grundlegendes wie unbekannte Klassen, Funktionen und Methoden, mittlere Stufen Rückgabetypen und die Typen übergebener Argumente, die oberen Stufen fehlende Typangaben, Nullwerte und den Umgang mit mixed.
Das Problem bei Altcode: Auf einer höheren Stufe melden sich sofort Hunderte Fehler. Die Baseline löst das. PHPStan legt die aktuell gemeldeten Fehler in einer Datei ab und meldet sie danach nicht mehr, sodass nur neuer und geänderter Code geprüft wird. Die Dokumentation nennt dafür einen Rahmen: Die Baseline passt, wenn einige Dutzend bis einige Hundert Fehler anstehen. Bei 15.000 Fehlern rät sie, die Konfiguration zu überarbeiten oder eine niedrigere Stufe zu wählen.
So sieht der Aufruf aus, der die Baseline erzeugt (Beispiel mit Stufe 5):
vendor/bin/phpstan analyse --level 5 \
--configuration phpstan.neon \
src/ --generate-baselineDie Datei phpstan-baseline.neon wird danach in die Konfiguration eingebunden:
includes:
- phpstan-baseline.neon
parameters:
level: 5
paths:
- srcDie Dokumentation warnt davor, die Baseline bei jedem neuen Fehler neu zu erzeugen. Sie wächst dann mit unlösbaren Einträgen, kennt keine Zeilennummern und erlaubt keine Kommentare. Ihr Lebensziel sei, nicht mehr zu existieren. Bei mir sinkt die Zahl der Einträge mit jedem Pull Request. Bei Einträgen, die nicht mehr vorkommen, meldet PHPStan das selbst, und mit --fix lassen sie sich aus der Datei entfernen.
Rector: automatisch umbauen, aber in kleinen Stücken
Rector schreibt PHP-Code automatisiert um, etwa bei PHP-Upgrades. Das Risiko ist die Menge. Die Dokumentation zu den Leveln beschreibt es selbst: Ein vorbereitetes Regelset ändert in einem Altprojekt schnell den größten Teil aller Dateien in einem Lauf, und niemand kann das prüfen. Ein Level ist deshalb die Liste der ersten N Regeln eines Sets, sortiert von der sichersten zur komplexesten. Level 0 aktiviert eine Regel, Level 1 zwei, und so weiter.
Die Konfiguration aus der Dokumentation, die ich als Ausgangspunkt nehme:
<?php
use Rector\Config\RectorConfig;
return RectorConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
->withPhpLevel(0);withPhpLevel() deckt die PHP-Upgrade-Regeln ab, und Rector geht dabei nur bis zu der PHP-Version, die in Ihrer composer.json steht. Daneben gibt es Level für die Typabdeckung (withTypeCoverageLevel()), für toten Code, Codequalität und Coding-Style. Der Probelauf ist vendor/bin/rector process --dry-run, die Änderung folgt erst mit vendor/bin/rector process.
Mein Ablauf pro Level: Probelauf, Diff lesen, Lauf, Charakterisierungstests, PHPStan, Pull Request, Prüfung durch Sie, Merge. Dann das nächste Level. Wenn ein Schritt die Tests rot färbt, sage ich Ihnen schriftlich, welche Regel das war und ob ich sie überspringe oder den Test anpasse.
Warum die drei Werkzeuge zusammengehören
| Werkzeug | Beantwortet die Frage | Ohne die anderen |
|---|---|---|
| PHPUnit | Tut die Anwendung noch dasselbe? | Prüft nur, was ein Test abdeckt |
| PHPStan | Passen die Typen und Aufrufe zusammen? | Findet keine fachlichen Abweichungen |
| Rector | Wie kommt der Code auf eine neuere Version? | Ändert viel, ohne zu belegen, dass nichts kaputtgeht |
PHPStan mit Baseline gibt mir die Fehlerliste, Rector baut um, und die Charakterisierungstests sagen, ob das Ergebnis dasselbe tut wie zuvor. Jedes Werkzeug allein reicht nicht.
So läuft die Zusammenarbeit
- Anfrage schriftlich. Sie schicken mir Ziel, Termin und den heutigen Stand.
- Rückfragen. Technische Fragen stelle ich schriftlich, und den Code lese ich nur in dem Umfang, den Sie freigeben.
- Umfang und Annahmen. Schriftlich steht dann, was zum Auftrag gehört, was nicht und welche Annahmen ich treffe. Taucht später etwas Neues auf, schätze ich es gesondert.
- Umsetzung auf einer Kopie. Den jeweiligen Stand können Sie jederzeit auf einer Testumgebung ansehen. Jede Änderung landet als Commit in einem Pull Request, den Sie in Ihrem Repository prüfen.
- Abnahme. Sie nehmen die Arbeit gegen die vereinbarten Kriterien ab. Was nicht besteht, bessere ich nach, bevor etwas live geht.
- Übergabe. README, Hinweise zur Bereitstellung, die Liste der Konfigurationswerte ohne Geheimnisse und die Liste der offenen Auffälligkeiten aus den Charakterisierungstests.
Gestaltung und Grafik kommen von Ihnen. Fehlt eine Vorlage, schicke ich Ihnen eine Tabelle, in der Sie je Ansicht markieren, welche Elemente wohin gehören.
Was ich von Ihnen brauche
| Zugang oder Angabe | Wozu |
|---|---|
| Lesezugriff auf das Repository | Ich sehe Versionen, Historie und vorhandene Tests. |
Ausgabe von php -v und composer show | Ich erkenne, welche PHP-Version und welche Pakete laufen. |
| Kopie der Anwendung mit pseudonymisierter Datenbank | Ich teste dort, nie zuerst auf der Produktion. |
| Eine Ansprechperson für Fachfragen | Ich kläre erwartetes Verhalten schriftlich mit ihr. |
| Liste der Fremdsysteme, die angebunden sind | Ich plane Schnittstellen und deren Ausfälle ein. |
Checkliste: ist Ihr Altcode bereit für eine Übernahme?
- Gibt es eine
composer.jsonmit festgelegten Versionen, und istcomposer.lockim Repository? - Lässt sich die Anwendung lokal oder auf einer Testumgebung starten, ohne die Produktion anzufassen?
- Gibt es eine Datenbank-Kopie, in der Namen und Adressen ersetzt sind?
- Wissen Sie, welche drei Abläufe in der Anwendung nicht ausfallen dürfen?
- Weiß jemand, welche Fremdsysteme sie aufruft?
- Ist die Quelle des Codes geklärt: Wer hat ihn geschrieben, und gibt es Nutzungsrechte?
Die Antworten müssen nicht vollständig sein. Aus dem, was Sie wissen, mache ich eine Liste offener Fragen.
Häufige Fragen
Wie übernehmen Sie PHP-Code, zu dem es keine Tests gibt?
Ich schreibe zuerst Tests, die festhalten, was der Code heute tut, auch wenn das Ergebnis nicht schön ist. Erst wenn diese Tests laufen, ändere ich etwas. So sehen Sie bei jeder Änderung, ob sich das Verhalten verschoben hat.
Was ist eine PHPStan-Baseline, und warum brauche ich sie?
Die Baseline ist eine Datei, in der PHPStan die zum Zeitpunkt der Erzeugung gemeldeten Fehler ablegt und danach nicht mehr meldet. Dadurch prüft PHPStan auf einer höheren Stufe sofort neuen und geänderten Code, ohne dass vorher alle alten Fehler behoben sein müssen.
Wie hoch sollte die PHPStan-Stufe sein?
Das hängt vom Ausgangspunkt ab. PHPStan hat Stufen von 0 bis 10, und die Stufen bauen aufeinander auf. Ich beginne dort, wo die Anwendung ohne Baseline schon fehlerfrei ist, und hebe von da an Stufe für Stufe an.
Ändert Rector mein Verhalten oder nur den Stil?
Rector schreibt Code automatisiert um, deshalb gehört jeder Lauf auf eine Kopie und in einen kleinen Pull Request. Ich lasse zuerst einen Probelauf ohne Änderungen laufen, lese den Diff und führe die Charakterisierungstests aus, bevor etwas in Ihr Repository kommt.
Brauche ich für die Arbeit auf einer Kopie einen Auftragsverarbeitungsvertrag?
Enthält die Kopie personenbezogene Daten und kann ich darauf zugreifen, verarbeite ich sie in Ihrem Auftrag. Dann ist nach Art. 28 DSGVO ein Vertrag nötig. Besser ist eine Kopie mit pseudonymisierten Daten, dann stellt sich die Frage oft gar nicht.
Gibt es Termine in Bielefeld oder Telefonate?
Nein. Von der Anfrage bis zur Abnahme läuft alles schriftlich, auch die Rückfragen und der Zugang zur Testumgebung. Jede Entscheidung bleibt nachlesbar.
Liefern Sie auch Layouts und Grafik?
Nein. Gestaltung, Mockups und Grafik bringen Sie mit. Ich übernehme die Umsetzung im Frontend und die Anwendung dahinter.
Ihre Anfrage an mich
Über das Kontaktformular erreichen Sie mich schriftlich. Nennen Sie die Adresse der Anwendung oder des Repositories, ihren Zweck, Ihren Termin und den Stand: PHP-Version, Framework, vorhandene Tests. Ich antworte schriftlich: zuerst mit offenen Fragen, danach mit einer Einschätzung des Umfangs. Die erste schriftliche Einschätzung ist kostenlos und verpflichtet Sie zu nichts. Alle PHP-Leistungen im Überblick stehen auf der Seite PHP-Entwickler. Läuft die Anwendung auf WordPress, sehen Sie sich WordPress-Wartung in Bielefeld an.
Ausgewählte Projekte
Beispiele aus meiner Arbeit.
olshtyn.com - WordPress Projekt | WPPoland
Die Website olshtyn.com ist ein modernes Informationsportal, das für Einwohner und Touristen entwickelt wurde, die sich für das Leben und die Attraktionen de...
osemka.pl - WordPress Projekt | WPPoland
Osemka.pl (auch bekannt als 8.pl) ist ein soziales Netzwerk, das in den Jahren 2006-2007 als Ort der Integration von Nutzern im Zeitalter des frühen sozialen...
predko.pl - WordPress Projekt | WPPoland
predko.pl ist ein moderner Online-Dienst, der dem Leben und der Karriere des Rallyefahrers Krzysztof Predko gewidmet ist. Die Seite wurde für Motorsportfans ...
WordPress Support & Entwicklung in Bielefeld
Brauchen Sie die Leistung: PHP-Entwickler in Bielefeld?
Beschreiben Sie Ihr Projekt per E-Mail. Antwort innerhalb von 48 Stunden.
Projekt beschreibenWeitere WordPress-Dienste und Wissensbasis entdecken
Individuelle WordPress-Entwicklung und Architektur.
Shops, Checkout-Prozesse und Verkaufslogik.
Shopify-Themes, Liquid und WooCommerce → Shopify-Migrationen.
Headless WordPress, Sanity, Strapi und Contentful mit Astro oder Next.js.
Claude, OpenAI und RAG in WordPress mit BYOK und EU-Residenz.
Geschäftsprozessautomatisierung rund um WordPress und Firmensysteme.
Bibliothek konkreter Automatisierungsfälle.
NIS2- und DORA-Scoping, Lieferantenregister, Incident-Runbook.
Verwandte Kategorien
Unterstützende Artikel

Ein Leitfaden aus der Praxis für eine WordPress-Website, die 2026 rankt. Technisches SEO, Core Web Vitals, Schema, AEO, GEO, hreflang und die Reihenfolge, mit der es beim ersten Mal klappt.

Migration von Shopify zu WooCommerce ohne Datenverlust, Kundenverlust oder SEO-Ranking-Einbußen. Umfasst Produkttransfer, 301-Weiterleitungen, URL-Mapping, WP-CLI-Automatisierung und Checkliste nach der Migration.

Die vollständige Checkliste nach der WordPress-Installation. 50 Schritte zu Sicherheit, Performance, SEO und Backups. Eine professionelle Konfiguration ab dem ersten Tag.