Debugging in PHP

Debuggen von PHP-Applikationen war für mich in den letzten 14 Jahren stets ein Thema mit dem ich mich nie beschäftigen wollte. Teils aus Bequemlichkeit, teils aus Unkenntnis. Auch kenne ich zahlreiche PHP Entwickler denen es damit genau so ergeht. Dass PHP nunmal als Interpretersprache nicht von Haus aus Debugging mit der IDE bereitstellt, hat es der Sache daher nie leicht gemacht. Aus diesem Grund habe ich mich in den letzten Jahren mit Debugging nie beschäftigt. Ich tat dies immer wieder als komplexes Hexenwerk ab und knüppelte es als unausgereift nieder. Damit begab ich mich – nur um mich selbst zu beschönigen – stets mit File-Logging und echo bzw. var_dump()-Ausgaben zufrieden.

Jedoch sind die gewonnen Erkenntnisse einer Debugsession unermesslich, da man zur Laufzeit exakt sehen kann welche Werte eine Variable in bestimmten Situationen beinhaltet. Ich habe seit Einrichtung dessen viele Stunden an Mühen mir ersparen können, da die erkannten Abläufe in einer Debugsession deutlich früher zu verwertbaren Resultaten führen.

Das kann nun ein Ende auch für Dich haben, denn die Einrichtung mittels X-Debug und der IDE PhpStorm ist denkbar einfach.

Grundsätzliches

Die hier vorgestellte Konfiguration betrifft erst einmal PhpStorm, jedoch kann ich mir vorstellen, dass diese unter Eclipse sowie den anderen gängigen IDEs mit nur minimal abweichenden Konfigurationseinstellungen vorzunehmen sein sollte. Denn die hier zugrunde liegenden Grundeinstellungen und Konzepte sind für alle die gleichen.

Für die Einrichtung und der Benutzung des Debuggers werde ich zum einen für den Abruf im Firefox-Browser, des weiteren auf der Linux-Konsole sowie abschließend im Rest Client – welcher in PhpStorm als Plugin installiert werden kann – beschrieben. X-Debug wurde als Modul auf einem Linux Server installiert und aktiviert und ich kann die Konfiguration nun in folgende Punkte zusammenfassen:

Servereinrichtung

Um X-Debug auf dem Server einzurichten bedarf es lediglich der Modulaktivierung in der php.ini:

zend_extension = /opt/remi/php73/root/usr/lib64/php/modules/xdebug.so
xdebug.remote_enable=1
xdebug.remote_autostart=0
xdebug.remote_handler=dbgp
;xdebug.remote_host=192.168.1.10 <-IGNORE THIS+USE remote_connect_back
xdebug.remote_connect_back=1
xdebug.remote_port=9000
xdebug.idekey=PHPSTORM
xdebug.remote_log=/tmp/xdebug.log

Durch Aktivierung der Option remote_connect_back wird automatisch IP-Adresse des anfragenden Browsers verbunden. Dies funktioniert in den meisten Fällen wunderbar und kann problemlos in lokalen Netzwerken aktiviert werden.

Einrichtung in PhpStorm

  • Settings öffnen und zu Debugger wechseln
    • XDEBUG PHP-IDE Key setzen: PHPSTORM
    • Port 9000 und 9001 wählen
    • Die Option “Break at first line in PHP Scripts” zunächst aktivieren
  • Debugger einrichten (Run/Debug Configurations)
    • Neue „PHP Web Application“
      • Neuen Server eintragen: URL und Port 80
      • Start URL: „/“
      • Pathmapping aktivieren
        • Hauptverzeichnis mappen mit dem jeweiligen serverseitigen Pfad
        • Gegebenfalls Unterverzeichnis auf weiteren Pfaden mappen.
      • Es wird eine Einstellung für http und https benötigt, falls https nicht erstellt wurde, macht dies PHP-Storm eigenmächtig, muss jedoch dann auch wie o.g. konfiguriert werden
    • Neue „PHP Remote Debug“
      • Servers hinzufügen („…“ wählen) und neuen Server hinzufügen
        • Servername setzen
        • Hostname setzen
        • Port kann auf 80 gesetzt werden
        • Pathmapping wie o.g. aktivieren
      • Den IDE-Key belegen mit „PHPSTORM“
    • Im Debugger springt PhpStorm in den Standardeinstellungen beim Start einer neuen Debugsitzung immer wieder in die Console. Mit Rechtsklick auf den Tab die Einstellung „Focus on startup“ abwählenPHPStorm

Der Port 9000 muss nun selbstverständlich in der Firewall für eingehende Verbindungen freigeschaltet werden.

Für den ersten Debug muss entweder ein beliebiger Breakpoint gesetzt werden bei dem der Debugger anhält. Alternativ kann im Menü -> Run die Option “Break at first line in PHP scripts” gesetzt werden. Dies jedoch ist für den alltäglichen Gebrauch nicht geeignet, außer man weiß zu Beginn rein gar nicht wohin der Abruf geroutet wird oder man wissen möchte welche Stellen noch relevant sind für die Ausführung sind.

REST Client (PhpStorm)

  • Header setzen
    • Accept: */*
    • Cache-Control: no-cache
  • Request Parameters XDEBUG_SESSION_START hinzufügen
    • Der Inhalt dieser Variable kann beliebig gesetzt werden und sogar leer bleiben
    • Dieser Wert wird serverseitig zu einem Cookie
  • Request zusammensetzen
    • Methode setzen (GET, PUT, POST, HEAD, DELETE)
    • Host setzen
    • Path mit dem Pfad und dem Zielskript befüllen
  • Debugger starten (Icon mit Telefonhörer)
  • Request absetzen

Firefox Browser

  • Plugin “The easiest Xdebug” installieren
  • IDE-Key eintragen: netbeans-xdebug
  • Debugging durch Seitenabruf initiieren

Einrichtung im Chrome

  • Die App “Header Hacker” über den Chrome Webstore suchen und installieren
  • Unter “Custom Request Headers” einen Eintrag einstellen:
    • Title: X-Debug
    • Header: Cookie
    • Append/&Replace: Append
    • String: XDEBUG_SESSION=PHPSTORM
    • Match String: #LEER LASSEN#
  • Unter „Permanent Header Switches“ ebenfalls einen neuen Eintrag einstellen:
    • Domain: Domain eintragen unter welcher der Header mitgesendet werden soll – z.B. http://debug.moderlak.de
    • Header Switch: Auswählen des oben eingetragenen Wert
  • Nachteil: Der Header muss immer manuell pro Domain konfiguriert werden und er wird immer mitgesendet. Daher schaltet man am besten den Debugger in der IDE ein und aus.

CLI Debugging

Die .bashrc wie folgt konfigurieren

Einrichtung der .bash.rc

Festlegen der CLIENTIP um die Verbindung zur lokalen IDE zu definieren und einen Alias um PHP-Skripte mit den umfassenden Parametern zu starten:

CLIENTIP=$(w -i|egrep -o "$USER\W*pts/([0-9]{1,3})\W*(([0-9]{1,3}).){3}.([0-9]{1,3}).*" | head -n1 | awk "{print \$3}")
# Alternative wenn anstelle der IP-Adresse der Computername im Netzwerk angezeigt wird - dies funktioniert zuverlässig wenn nur ein Benutzer mit dem Server per SSH verbunden ist:
# CLIENTIP=$(netstat -tn 2>/dev/null | grep :22 | awk '{print $5}' | grep -v :22 | cut -d: -f1 | sort | uniq | sort -nr | head)

alias xphp="XDEBUG_CONFIG=\"idekey=PHPSTORM\" PHP_IDE_CONFIG=serverName=\"$HOSTNAME(CLI)\" php -d \"xdebug.remote_host=$CLIENTIP\" -d \"xdebug.remote_connect_back=0\" -d \"xdebug.remote_port=9000\" -d \"xdebug e_enable=1\""

CLI Debugging lokal unter Windows

Inzwischen wurde ich auch dazu genötigt unter Windows zu debuggen, welches jedoch nicht im Browser, sondern nur auf der Konsole ausgeführt wird. Dies einzurichten und zu nutzen ist allerdings recht einfach und bedarf nur weniger Schritte der Konfiguration.

Hierfür muss zunächst die Extension heruntergeladen und in das Unterverzeichnis von php unter “ext” abgelegt werden. Die DLL erhält man von https://xdebug.org/ aus der Sektion Download.

In der php.ini wird die Extension als “zend_extension” aktiviert mit dem Namen der geladenen DLL-Datei.

Dann legt man lokal für den eigenen Benutzer eine neue Umgebungsvariable wie folgt an:

Name: XDEBUG_CONFIG
Wert: remote_enable=1 remote_mode=req idekey=PHPSTORM

Abschließend wird nun in dem zu debuggenden Skript in der IDE ein Breakpoint gesetzt und das Skript einfach via php aufgerufen. Es sind keine weiteren Parameter notwendig.

Troubleshooting

Jedes beliebige PHP-Skript kann nun mit xphp myscript.php anstelle von php myscript.php gestartet werden. Dabei werden die notwendigen Header dem Skriptabruf angehangen, die das Debugging initiieren und man somit durch den Code navigieren kann.

Wenn es mal nicht so läuft wie gewünscht habe ich mal die typischen Fehlermeldungen zusammengetragen:

  • Nach der Formularabsendung blockiert der Browser und zeigt nur noch den Hinweis: “Fehler: Gesicherte Verbindung fehlgeschlagen“
    • Problem: Debugging im PhpStorm aktiviert und Cookie XDEBUG_SESSION wird vom Browser gesendet. Dies passiert mir besonders häufig mit dem Plugin “The easiest Xdebug”. Mit einem Klick auf das Icon um den Cookie ein/auszuschalten ist nicht ausreichend, da der Cookie nicht mehr entfernt wird.
    • Lösung: Den Listener für Debugging im PhpStorm abschalten und den Cookie XDEBUG_SESSION im Browser explizit entfernen und Seite erneut abrufen.
  • CLI-Modus: PHPStorm antwortet nicht auf Debugrequest obwohl alle Daten korrekt eingegeben
    • Problem: Die lokale IP-Adresse des Clients im xphp-Aufruf unter xdebug.remote_host ist veraltet
    • Lösung: bashrc neuladen mittels: source ~/.bash.rc 

Diese Liste der Fehler wird im Laufe der Zeit gegebenenfalls erweitert.

Fazit

Mein Entwicklerdasein hat sich seit dieser Einführung um 180 Grad gewandelt, denn Probleme kann ich seither viel früher erkennen. Beim Durchlauf des Programms werden Erkenntnisse zu Tage gefördert, welche beim sonst üblichen Komplettdurchlauf nur selten sofort ersichtlich sind.
Auch lassen sich mögliche Fehler hiermit sehr schnell aufspüren und exakt analysieren.


Hat Dir mein Beitrag gefallen?

Unterstütze meine Arbeit und werde noch heute Patreon!

Veröffentlicht von

Sebastian

Als Softwareschmied entwickelt Sebastian seit zwanzig Jahren Individualsoftware mit den Schwerpunkten PHP und MySQL auf diversen Linux-Systemen. Er hat eine pfiffige Frau sowie drei quirlige Söhne, fährt gerne Fahrrad und liebt handwerkliche Arbeiten die im häuslichen Umfeld so anfallen.