für saubere Massenänderungen in PhpStorm
Normales Find/Replace und Regex-Suche sind blind für PHP-Semantik. Structural Search and Replace versteht den Abstract Syntax Tree – und ersetzt exakt das, was der Code strukturell bedeutet, nicht was er buchstäblich enthält. Das Ergebnis: sichere, semantisch korrekte Massenänderungen ohne Fehlalarme.
Inhaltsverzeichnis
- 1. Warum normales Find/Replace bei Refactorings scheitert
- 2. Structural Search: Templates und AST-Grundlagen
- 3. Template-Variablen und Constraints konfigurieren
- 4. Replace-Templates: Treffer sicher transformieren
- 5. SSR-Inspections als dauerhafte Codequalitäts-Regeln
- 6. PHP 8.4 Migration mit SSR durchführen
- 7. Magento-spezifische SSR-Anwendungsfälle
- 8. SSR-Templates versionieren und im Team teilen
- 9. SSR vs. Regex vs. Rector im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Warum normales Find/Replace bei Refactorings scheitert
Ein einfaches Find/Replace für den Ausdruck array() zu [] klingt trivial – bis man feststellt, dass die Suche auch in Kommentaren, Strings und Docblocks trifft. Oder dass array(1, 2) im Ergebnis korrekt zu [1, 2] wird, aber array ( mit Leerzeichen übersehen wird. Regex löst das Leerzeichen-Problem, versteht aber keine PHP-Semantik: Es unterscheidet nicht zwischen einem Array-Literal in einem String und einem echten PHP-Ausdruck.
Structural Search and Replace (SSR) in PhpStorm arbeitet auf dem Abstract Syntax Tree (AST), nicht auf dem Rohtext. Ein SSR-Template für array($args$) trifft genau PHP-Array-Ausdrücke – egal wie sie formatiert sind, ob mit oder ohne Leerzeichen, inline oder mehrzeilig. Kommentare und Strings werden automatisch ausgeschlossen, weil sie im AST eine andere Struktur haben als Ausdrücke. Das Ergebnis sind Suchtreffer, die semantisch korrekt sind, nicht nur textuell ähnlich.
Der praktische Unterschied: Bei einem Magento-Modul mit tausend PHP-Dateien liefert eine Regex-Suche nach veralteten Konstrukten häufig Fehlalarme in Kommentaren und Strings, die manuell aussortiert werden müssen. SSR liefert nur echte Treffer im Ausführungspfad. Bei der anschließenden Ersetzung transformiert SSR das Konstrukt korrekt, auch wenn die ursprünglichen Treffer unterschiedlich formatiert waren – weil die Ersetzung auf AST-Ebene operiert.
2. Structural Search: Templates und AST-Grundlagen
SSR öffnet man in PhpStorm über Edit → Find → Search Structurally (Suchen) oder Search Structurally and Replace (Suchen und Ersetzen). Der Such-Dialog enthält ein Template-Feld, in das PHP-Code eingegeben wird. Dieser Code wird nicht als Text, sondern als AST-Pattern interpretiert. $x$ instanceof $Type$ ist ein Pattern, das jeden isinstance-Ausdruck trifft – unabhängig von Variablenname und Typname.
Das Contextdropdown legt fest, welchen PHP-Kontext das Template repräsentiert: Expression (Ausdruck), Statement (Anweisung), Class-Member, Methode usw. Für die meisten Refactorings ist Expression korrekt. Wenn man eine komplette Methode sucht oder eine Klasse mit bestimmten Eigenschaften, wählt man den entsprechenden Kontext. Ein falscher Kontext führt dazu, dass PhpStorm gültige Patterns nicht findet, weil die AST-Struktur nicht dem erwarteten Kontext entspricht.
Die Pattern-Syntax verwendet Variablen mit Dollarzeichen: $variable$ steht für einen beliebigen Ausdruck an dieser Position. $args$ als Parameterliste steht für eine beliebige Anzahl von Argumenten. Feste Teile im Template – wie Schlüsselwörter, Operatoren und Literal-Typen – werden exakt gemacht. new $ClassName$() trifft jeden Konstruktoraufruf ohne Argumente, new $ClassName$($args$) trifft Konstruktoraufrufe mit beliebig vielen Argumenten.
3. Template-Variablen und Constraints konfigurieren
Die Macht von SSR liegt in den Variable Constraints. Für jede Template-Variable kann man einschränken, wie oft sie vorkommen darf (Quantifier), ob sie auf einen bestimmten Typ beschränkt ist, ob sie regulär ausgedrückt werden kann und ob sie negiert werden soll. Ein Constraint Min: 0, Max: unbegrenzt macht die Variable optional. Ein Regex-Filter auf einer Variablen schränkt ein, welche Texte passen – etwa nur Variablennamen, die mit einem Großbuchstaben beginnen, für Klassen-Constraints.
Der Type filter ist besonders wertvoll: $object$ mit Typ-Filter \Magento\Framework\App\RequestInterface trifft nur Methodenaufrufe auf Objekten, die diesen Typ haben. PhpStorm nutzt dabei seine Typinferenz, um den Typ zur Compile-Zeit zu bestimmen. Das macht SSR zu einem echten semantischen Suchbegriff – nicht nur ein Textmuster, sondern ein typbewusstes Suchmuster, das falsche Treffer auf anderen Typen ausschließt.
Der Not-Filter erlaubt es, bestimmte Muster auszuschließen. Ein Template, das alle Methodenaufrufe sucht außer denen auf $this, kombiniert eine Variable mit einem Nicht-Filter auf this. Diese Kombination aus Quantifizierung, Typ-Filter und Negation macht SSR-Templates präzise genug für echte Refactoring-Aufgaben in großen Codebases.
<?php
// SSR Such-Template: Veralteten array()-Konstruktor finden
// Template-Kontext: Expression
// Suchfeld: array($args$)
// Ersetzungsfeld: [$args$]
//
// Damit wird aus:
$config = array('key' => 'value', 'enabled' => true);
// Exakt:
$config = ['key' => 'value', 'enabled' => true];
// SSR Such-Template: isset() + ternary durch Null-Coalescing ersetzen
// Suchfeld: isset($x$) ? $x$ : $default$
// Ersetzungsfeld: $x$ ?? $default$
//
// Beispiel-Treffer (alle semantisch äquivalent, alle werden gefunden):
$name = isset($data['name']) ? $data['name'] : 'Unknown';
$price = isset($product->price) ? $product->price : 0.0;
$label = isset($config['label']) ? $config['label'] : null;
// SSR-Ergebnis (semantisch korrekt transformiert):
$name = $data['name'] ?? 'Unknown';
$price = $product->price ?? 0.0;
$label = $config['label'] ?? null;
4. Replace-Templates: Treffer sicher transformieren
Das Replace-Template verwendet dieselben Variablennamen wie das Search-Template. Die Variable $args$ im Such-Template wird im Replace-Template durch den tatsächlich gefundenen Code ersetzt. Das Replace-Template selbst ist wieder PHP-Code – mit der Einschränkung, dass es dasselbe AST-Konstrukt wie das Suchergebnis repräsentieren muss. Ein Search-Template für einen Ausdruck muss auch ein Ausdruck als Replace-Template haben.
PhpStorm verwaltet bei der Ersetzung automatisch die Formatierung. Das Replace-Template wird nicht als Rohtext eingefügt, sondern durch den Code-Formatter geleitet. Das bedeutet, dass auch mehrzeilige Treffer korrekt eingerückt werden – ohne dass man in der Ersetzung explizit Leerzeichen und Einrückungen berücksichtigen muss. Das ist ein erheblicher Vorteil gegenüber Regex-Ersetzungen, bei denen Formatierungsdetails manuell abgebildet werden müssen.
Für komplexe Transformationen, bei denen mehrere Teile des gefundenen Codes in einer neuen Struktur zusammengesetzt werden, unterstützt SSR mehrere Template-Variablen im Replace-Teil. $object$->$method$($args$) als Suche und $object$->newMethod($method$, $args$) als Ersetzung – so wird ein Methodenaufruf umgebaut, wobei der alte Methodenname als erstes Argument des neuen Aufrufs übergeben wird. Solche Transformationen wären mit Regex kaum korrekt zu formulieren.
5. SSR-Inspections als dauerhafte Codequalitäts-Regeln
SSR-Templates können als Custom Inspections in PhpStorm gespeichert werden. Damit werden sie zu dauerhaften Code-Qualitätsregeln, die PhpStorm in jedem geöffneten File automatisch prüft – genauso wie die eingebauten Inspections. Eine Custom Inspection für array($args$) würde jede Verwendung der alten Array-Syntax gelb unterstreichen, mit einer Meldung und einem Quick-Fix-Button für die automatische Transformation zu [$args$].
Das Einrichten einer Custom Inspection aus einem SSR-Template erfolgt über Settings → Editor → Inspections → PHP → General → Custom. Das Template wird inklusive der Ersetzung gespeichert. Severity, Scope und Quick-Fix-Verfügbarkeit sind konfigurierbar. Eine Custom Inspection mit Severity Error wird im Code rot unterstrichen und erscheint im Problems-Tab – sie verhält sich exakt wie eine eingebaute Inspection, ist aber projektspezifisch und versionierbar.
Für Teams ist das der wichtigste Anwendungsfall von SSR. Statt in Code-Reviews manuell auf veraltete Muster zu achten, definiert man Custom Inspections, die PhpStorm im Hintergrund prüft. Neue Entwickler bekommen sofort Hinweise, wenn sie veraltete Konstrukte verwenden, ohne dass ein Reviewer eingreifen muss. Die Custom Inspections können als Teil der Inspection-Profile-XML-Datei versioniert werden.
6. PHP 8.4 Migration mit SSR durchführen
Die Migration von PHP 8.1 auf 8.4 bringt mehrere syntaktische Verbesserungen, die sich ideal für SSR-Migration eignen. Property Hooks in PHP 8.4 erlauben es, Getter und Setter direkt in Klasseneigenschaften zu definieren. Eine Migration von klassischen getX()/setX()-Paaren ist komplex und gehört eher in den Rector-Bereich. Aber einfachere Migrationen – wie das Ersetzen von intval($x) durch (int) $x oder das Ersetzen von strval($x) durch (string) $x – sind exakt das Anwendungsgebiet von SSR.
Für Magento-Projekte, die auf PHP 8.4 migrieren, sind SSR-Templates für Constructor Property Promotion besonders nützlich. Das Muster: Eine Klasse hat eine Property-Deklaration und im Konstruktor eine Zuweisung $this->property = $param. Das vollständige SSR-Template für diese Transformation ist komplex, weil es Class Member als Kontext braucht – aber für einfache Fälle ohne komplexe Docblocks ist es machbar und spart erheblich manuelle Arbeit.
<?php
// SSR-Template 1: intval() durch (int) Cast ersetzen
// Such-Template: intval($x$)
// Ersatz-Template: (int)$x$
// Constraint auf $x$: Nicht leer, Expression-Kontext
// Vorher:
$entityId = intval($request->getParam('id'));
$storeId = intval($this->storeManager->getStore()->getId());
$qty = intval($item->getQty());
// Nachher (alle mit einem einzigen SSR-Replace):
$entityId = (int)$request->getParam('id');
$storeId = (int)$this->storeManager->getStore()->getId();
$qty = (int)$item->getQty();
// SSR-Template 2: strval() durch (string) ersetzen
// Such-Template: strval($x$)
// Ersatz-Template: (string)$x$
// SSR-Template 3: count($arr$) > 0 durch !empty($arr$)
// Such-Template: count($arr$) > 0
// Ersatz-Template: !empty($arr$)
// Hinweis: Semantisch äquivalent für Arrays, nicht für Countable-Objekte
// Constraint $arr$: Typ-Filter array (PhpStorm-Typinferenz nutzen)
7. Magento-spezifische SSR-Anwendungsfälle
In Magento-Projekten gibt es wiederkehrende Muster, die sich hervorragend für SSR eignen. Das Ersetzen von direkten Mage::getModel()-Aufrufen in Legacy-Code durch korrekte Dependency Injection, das Finden aller Stellen, wo $block->getData('key') statt der typsicheren Getter-Methoden verwendet wird, oder das Identifizieren aller ObjectManager::getInstance()-Aufrufe, die in Magento 2 als Anti-Pattern gelten und durch Dependency Injection ersetzt werden sollten.
Ein praktisches Beispiel: Alle Stellen finden, wo $this->_objectManager verwendet wird – ein Hinweis auf direkten ObjectManager-Zugriff, der vermieden werden soll. Das SSR-Template $this->_objectManager->$method$($args$) trifft genau diese Stellen. Mit dem Inspection-Modus werden sie dauerhaft als Warnung markiert, bis sie durch korrekte Constructor-Injection ersetzt sind. Das ist der direkte Weg von Code-Standard-Dokument zu automatisch durchgesetzter Regel.
Ein weiterer Magento-Anwendungsfall: Das Finden aller Stellen, wo __DIR__ in einer Weise verwendet wird, die mit dem Magento-Module-Directory-API kollidiert. Oder das Identifizieren aller Template-Dateien, die $block->escapeHtml() vermissen, indem man im PHP-Code nach direktem Echo von Variablen ohne Escaping sucht. SSR-Templates können diese Muster präzise und falsch-alarm-frei finden.
8. SSR-Templates versionieren und im Team teilen
SSR-Templates werden in PhpStorm als Inspection-Profile gespeichert. Inspection-Profile können als XML exportiert werden und liegen im .idea/-Verzeichnis des Projekts. Wer diese Dateien ins Repository eincheckt, stellt sicher, dass alle Entwickler dieselben Custom Inspections und Quick-Fixes verfügbar haben. Das Einrichten ist einmalig – danach erben alle neuen Entwickler die Regeln automatisch beim Clone.
Für das strukturierte Versionieren von SSR-Templates empfiehlt sich ein .idea/inspectionProfiles/Project_Default.xml, das alle projektspezifischen Custom Inspections enthält. Dieses File kann im Code-Review begutachtet werden, wenn neue Regeln hinzukommen. Wichtig: Das Inspection-Profil muss im Projekt als aktives Profil gesetzt sein, damit alle Entwickler dieselben Warnungen sehen. Das active Profile ist in .idea/workspace.xml hinterlegt, das normalerweise in .gitignore steht.
9. SSR vs. Regex vs. Rector im Vergleich
Die Wahl des richtigen Werkzeugs für Code-Transformationen hängt von der Komplexität der Änderung, der erforderlichen Präzision und der Teamkonstellation ab. SSR, Regex und Rector haben klar abgegrenzte Stärken und Schwächen.
| Kriterium | SSR (PhpStorm) | Regex Find/Replace | Rector |
|---|---|---|---|
| PHP-Semantik | AST-basiert, typsensitiv | Textbasiert, blind | AST-basiert, vollständig |
| Fehlalarme | Sehr selten | Häufig (Strings, Kommentare) | Sehr selten |
| Lernaufwand | Gering (PHP-Syntax als Template) | Mittel (Regex-Kenntnis) | Hoch (PHP, Rector-API) |
| Inspection-Integration | Ja, Custom Inspections | Nein | Via CI, nicht IDE-nativ |
| Komplexe Refactorings | Begrenzt | Sehr begrenzt | Vollständig |
SSR ist das richtige Werkzeug für mittlere Komplexität: Suchen und Ersetzen von bestimmten Ausdrucksmustern mit PHP-Semantik, ohne eine vollständige Rector-Regel schreiben zu müssen. Für einfache Textsuche genügt Regex. Für komplexe Migrations-Regeln, die mehrere Klassen betreffen, Typinformationen aus mehreren Dateien brauchen oder komplexe AST-Transformationen durchführen, ist Rector die richtige Wahl. SSR und Rector schließen sich nicht aus – viele Migrationsprojekte nutzen SSR für einfache Patterns und Rector für die komplexen.
Mironsoft
Magento 2 Refactoring · PHP 8.4 Migration · Code-Qualität
Magento-Code sicher auf PHP 8.4 migrieren?
Wir führen Magento-PHP-Migrationen mit SSR, Rector und PhpStan durch – mit Custom Inspections als dauerhaften Codequalitätsregeln und vollständiger Test-Absicherung vor jedem Refactoring-Schritt.
PHP-Migration
PHP 8.1 → 8.4 Migration mit SSR und Rector, vollständige Deprecation-Bereinigung
Custom Inspections
Magento-spezifische SSR-Regeln als Custom Inspections, damit Anti-Patterns dauerhaft verhindert werden
Code-Review
Bestehenden Magento-Code auf veraltete Muster analysieren und Refactoring-Plan erstellen
10. Zusammenfassung
Structural Search and Replace in PhpStorm ist die Lücke zwischen einfachem Find/Replace und vollständigem Rector: AST-basiert, ohne Fehlalarme in Strings und Kommentaren, mit Typ-Constraints für präzise Trefferauswahl und automatischer Formatierung bei der Ersetzung. Für PHP-Entwickler, die regelmäßig Refactorings in mittlerer Komplexität durchführen, ist SSR das schnellste und sicherste Werkzeug.
Der Sprung von einmaliger SSR-Suche zu dauerhafter Custom Inspection macht SSR zu einem strategischen Werkzeug für Codequalität. Einmal als Inspection gespeichert, prüft PhpStorm jede neue Codezeile auf das Muster – ohne manuelle Code-Reviews. Versioniert im Repository gelten die Regeln für das gesamte Team. Das Ergebnis ist eine konsistente Codebase, die Magento-Anti-Patterns und veraltete PHP-Konstrukte automatisch und dauerhaft verhindert.
Structural Search and Replace — Das Wichtigste auf einen Blick
AST-basierte Suche
Edit → Find → Search Structurally. PHP-Syntax als Template, keine Fehlalarme in Strings und Kommentaren. Variablen mit $name$ für flexible Muster.
Variablen-Constraints
Typ-Filter, Quantifier und Negation für präzise Trefferauswahl. Typ-Filter nutzt PhpStorm-Typinferenz für semantisch korrekte Suche.
Custom Inspections
SSR-Templates als dauerhafte Inspection speichern. Quick-Fix für automatische Transformation direkt in der IDE.
Team-Sharing
Inspection-Profile als XML versionieren in .idea/inspectionProfiles/. Einmal einrichten – alle Entwickler erben die Regeln beim Clone.