
Ich hatte kürzlich gelegentlich die Gelegenheit, mit mehreren alten PHP-Anwendungen zu arbeiten. Ich bemerkte einige häufige Anti-Muster, die behoben werden mussten. In diesem Artikel geht es nicht darum, wie Sie eine alte PHP-Anwendung umschreiben, um <hier den Namen des wunderbaren Frameworks einzufügen>, sondern um die Wartung zu vereinfachen und die Arbeit zu vereinfachen.
Antipattern # 1: Anmeldeinformationen im Code
Dies ist das häufigste der schlimmsten Muster, auf die ich gestoßen bin. In vielen Projekten wird versionierter Code mit wichtigen Informationen wie Namen und Kennwörtern für den Zugriff auf die Datenbank fest codiert. Dies ist offensichtlich eine schlechte Vorgehensweise, da keine lokalen Umgebungen erstellt werden können, da der Code an eine bestimmte Umgebung gebunden ist. Darüber hinaus kann jeder Benutzer mit Zugriff auf den Code Anmeldeinformationen anzeigen, die normalerweise für die Produktionsumgebung geeignet sind.
Um dies zu beheben, bevorzuge ich eine Methode, die für jede Anwendung funktioniert : Installieren Sie das Paket phpdotenv , mit dem Sie eine Umgebungsdatei erstellen und mithilfe von Umgebungsüberwachungsvariablen auf Variablen zugreifen können.
Erstellen wir zwei Dateien:
.env.exampleeine, die versioniert wird und als Vorlage für die Datei dient.env, die die Anmeldeinformationen enthält. Die Datei ist .envnicht versioniert, fügen Sie sie also hinzu .gitignore. Dies wird in der offiziellen Dokumentation gut erklärt .
In Ihrer Datei
.env.examplewerden die Anmeldeinformationen aufgeführt:
DB_HOST=
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
Und die Daten selbst werden in der Datei sein
.env:
DB_HOST=localhost
DB_DATABASE=mydb
DB_USERNAME=root
DB_PASSWORD=root
Laden Sie in einer regulären Datei
.env:
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
Kann dann beispielsweise mit auf die Buchhaltungsdaten angewendet werden
$_ENV['DB_HOST'].
Es wird nicht empfohlen, das Paket im Betrieb "wie es ist" zu verwenden, da dies besser ist:
- Fügen Sie Umgebungsvariablen in die Laufzeit Ihres Containers ein, wenn Sie eine Docker-basierte Bereitstellung haben, oder wenn möglich in die serverseitige HTTP-Konfiguration.
- Cache-Umgebungsvariablen, um den Aufwand für das Lesen von .env bei jeder Anforderung zu vermeiden. So macht es Laravel .
Anmeldeinformationsdateien können aus dem Git-Verlauf entfernt werden .
Antipattern # 2: Verwenden Sie keinen Composer
Früher war es sehr beliebt, einen lib-Ordner mit großen Bibliotheken wie PHPMailer zu haben. Dies sollte bei der Versionierung auf jede mögliche Weise vermieden werden, daher sollten diese Abhängigkeiten mit Composer verwaltet werden . Dann können Sie ganz einfach feststellen, welche Version des Pakets verwendet wird, und es gegebenenfalls aktualisieren.
Installieren Sie also Composer und verwalten Sie es.
Antipattern # 3: keine lokale Umgebung
Die meisten Anwendungen, mit denen ich gearbeitet habe, hatten nur eine Umgebung: die Produktion.

Indem Sie jedoch Anti-Pattern Nr. 1 entfernen, können Sie Ihre lokale Umgebung problemlos anpassen. Möglicherweise haben Sie einige Ihrer Konfigurationen fest codiert, z. B. Startpfade, aber jetzt können Sie diese verschieben
.env.
Ich benutze Docker, um lokale Umgebungen zu erstellen. Es funktioniert besonders gut für ältere Projekte, da sie häufig ältere Versionen von PHP verwenden, die Sie nicht installieren möchten oder können.
Sie können einen Dienst wie PHPDocker oder eine kleine Datei verwenden
docker-compose.yml.
Antipattern # 4: Verwenden Sie nicht den öffentlichen Ordner
Es stellte sich heraus, dass die meisten dieser alten Projekte über ihre Stammordner zugänglich sind. Das heißt, jede Datei im Stammverzeichnis kann öffentlich gelesen werden. Dies ist besonders schlimm, wenn Angreifer (z. B. ein Kiddie-Skript) versuchen, direkt auf die enthaltenen Dateien zuzugreifen, da Sie die Ausgabe möglicherweise nicht ermitteln können, wenn das Skript direkt auf alle enthaltenen Dateien zugreift.
Offensichtlich ist diese Situation nicht mit der Verwendung von
.envoder Composer kompatibel , da das Öffnen des Herstellerordners eine schlechte Idee ist . Ja, dazu gibt es einige Tricks . Verschieben Sie jedoch nach Möglichkeit alle für Clients geöffneten PHP-Dateien in einen Ordner Publicund ändern Sie die Serverkonfiguration so, dass dieser Ordner zum Stammordner für Ihre Anwendung wird.
Normalerweise mache ich das:
- Erstellen Sie einen Ordner
dockerfür Dateien, die sich auf Docker beziehen (Nginx-Konfiguration, PHP-Docker-Datei usw.). - Ich erstelle einen Ordner,
appin dem ich Geschäftslogik (Dienste, Klassen usw.) speichere. - Ich erstelle einen Ordner,
publicin dem ich PHP-Skripte und -Ressourcen (JS / CSS) speichere, die für Clients geöffnet sind. Dies ist aus Sicht der Clients der Stammordner der Anwendung. - Ich erstelle Dateien
.envund.env.example.
Antipattern # 5: ungeheure Sicherheitsprobleme
PHP-Anwendungen, insbesondere ältere, die keine Frameworks verwenden, leiden häufig unter schwerwiegenden Sicherheitsproblemen:
- Aufgrund des fehlenden Escapings von Parametern in der Abfrage besteht die Gefahr einer SQL-Injection. Um dies zu verhindern, verwenden Sie PDO!
- Aufgrund der Anzeige nicht maskierter Benutzerdaten besteht die Gefahr einer XSS-Injektion. Verwenden Sie htmlspecialchars, um sie zu verhindern.
- … . , , , .
- - CSRF-. Anti-CSRF, .
- Schlechte Passwortverschlüsselung. Ich habe gesehen, dass viele Projekte immer noch SHA-1 und sogar MD5 für das Passwort-Hashing verwenden. PHP 5.5 hat eine gute Unterstützung für BCrypt. Es ist eine Schande, es nicht zu verwenden. Um Passwörter bequem zu übertragen, aktualisiere ich lieber die Hashes in der Datenbank, wenn sich Benutzer anmelden. Die Hauptsache ist, sicherzustellen, dass die Spalte
passwordlang genug ist, um BCrypt-Passwörter aufzunehmen. VARCHAR (255) ist in Ordnung. Hier ist ein Pseudocode, um es klarer zu machen:
<?php // : $ // : if (strpos($oldPasswordHash, '$') !== 0 && hash_equals($oldPasswordHash, sha1($clearPasswordInput))) { $newPasswordHash = password_hash($clearPasswordInput, PASSWORD_DEFAULT); // password // : } // if (password_verify($clearPasswordInput, $currentPasswordHash)) { // : } // :
Antipattern # 6: keine Tests
Dies ist in älteren Anwendungen sehr häufig. Es ist kaum möglich, Unit-Tests für die gesamte Anwendung zu schreiben, sodass Sie Funktionstests schreiben können.

Hierbei handelt es sich um allgemeine Tests, mit denen Sie sicherstellen können, dass das spätere Refactoring Ihrer Anwendung diese nicht beschädigt. Tests können einfach sein. Wir starten beispielsweise den Browser und geben die Anwendung ein. Warten Sie dann auf den HTTP-Code für den Erfolg des Vorgangs und / oder die entsprechende Meldung auf der letzten Seite. Für Tests können Sie PHPUnit oder Cypress oder Codeception verwenden .
Antipattern # 7: Schlechte Fehlerbehandlung
Wenn (oder höchstwahrscheinlich wann) etwas kaputt geht, müssen Sie es schnell herausfinden. Viele ältere Anwendungen behandeln Fehler jedoch nicht gut und verlassen sich aus Gründen der Nachsicht auf PHP.
Sie müssen in der Lage sein, so viele Fehler wie möglich zu erfassen und zu protokollieren, um sie zu beheben. Es gibt gute Artikel zu diesem Thema .
Außerdem können Sie leichter Orte finden, an denen Fehler auftreten, wenn das System bestimmte Ausnahmen auslöst.
Antipattern # 8: globale Variablen
Ich dachte, ich würde sie nie wieder sehen, bis ich anfing, mit alten Projekten zu arbeiten. Globale Variablen machen das Lesen und Verstehen des Verhaltens des Codes unvorhersehbar. Kurz gesagt, es ist böse .
Es ist besser, stattdessen die Abhängigkeitsinjektion zu verwenden , da Sie damit steuern können, welche Instanzen wo verwendet werden. Zum Beispiel hat das Pimple- Paket eine gute Leistung erbracht .
Was kann man noch verbessern?
Abhängig vom Schicksal der Anwendung oder des Budgets können Sie mehrere weitere Schritte unternehmen, um Ihr Projekt zu verbessern.
Wenn die Anwendung auf einer älteren Version von PHP (unter 7) ausgeführt wird, versuchen Sie zunächst, sie zu aktualisieren. Meistens verursacht dies keine großen Probleme, und vor allem wird es die meiste Zeit dauern, um die Anrufe
mysql_ calls, falls vorhanden , loszuwerden . Um dies schnell zu beheben, können Sie eine ähnliche Bibliothek verwenden . Es ist jedoch besser, alle Anforderungen für PDO neu zu schreiben, damit alle Parameter gleichzeitig maskiert werden.
Wenn die Anwendung nicht das MVC-Muster verwendet, dh die Geschäftslogik und die Vorlagen getrennt sind, ist es Zeit, eine Vorlagenbibliothek hinzuzufügen (ich weiß, dass PHP eine Vorlagensprache ist, aber moderne Bibliotheken sind viel praktischer), z. B. Smarty, Twig oder Blade.
Auf lange Sicht ist es schließlich am besten, Ihre Anwendung in einem modernen PHP-Framework wie Laravel oder Symfony neu zu schreiben. Sie verfügen über alle Tools, die Sie für eine sichere und intelligente PHP-Entwicklung benötigen. Wenn die Anwendung groß ist, empfehle ich die Verwendung des Strangler- Musters , um ein Umschreiben des Urknalls zu vermeiden , das möglicherweise (und wahrscheinlich) schlecht enden wird. Daher können Sie die Teile des Codes, an denen Sie gerade arbeiten, auf das neue System migrieren und die alten Arbeitsteile intakt lassen, bis sie erreicht werden.
Dies ist ein effektiver Ansatz, mit dem Sie eine moderne PHP-Umgebung für Ihre tägliche Arbeit erstellen können, ohne die Funktionen je nach Projekt für Wochen oder Monate einzufrieren.