Xdebug mit WordPress, DDEV und PhpStorm

Immer wieder kommt man beim Entwickeln eines Plugins oder Themes für WordPress an den Punkt, an dem es mal nicht so läuft wie man möchte, und der Debugger angeschmissen werden muss. Ich nutze als lokale Entwicklungs­umgebung ein WordPress in DDEV und meine IDE ist die JetBrains IDE PhpStorm. Wie man beides mit Xdebug bestmöglichst verbindet, erkläre ich in diesem Post.

Ein Hinweis noch vorab: Ich öffne in PhpStorm immer direkt ein Plugin- oder Theme-Verzeichnis. Ich weiß, dass andere auch die ganze WordPress-Installation in der IDE öffnen, also das Root-Verzeichnis von WordPress. Das passt zu meinem Workflow aber nicht so gut. Das hier beschriebene Verfahren geht für beide Varianten, die Pfade müssen dann halt entsprechend angepasst werden.

Xdebug in DDEV aktivieren

Damit der Debugger überhaupt funktioniert, muss natürlich erstmal die PHP-Extension für Xdebug aktiviert werden. Da ein aktives Xdebug immer auch ein kleines bisschen Performance kostet, sollte man es nur aktiv haben, wenn man es wirklich grade nutzt.

Die CLI-Commands für DDEV sind da ganz einfach:

ddev xdebug on
ddev xdebug off

Oder, wenn man nicht immer wieder was anderes eingeben will, geht’s auch noch einfacher:

ddev xdebug toggle

Xdebug Einstellungen in PhpStorm

Jetzt wo Xdebug läuft, schaue ich kurz in die Xdebug-Einstellungen von PhpStorm und deaktiviere die Option »Force break at first line when a script is outside the project«. Diese möchte ich nicht aktiv haben, da ich, wie einleitend erwähnt, direkt das Plugin oder Theme in PhpStorm habe. Machst du das anders, kannst du die Option aktiviert lassen.

Screenshot der PhpStorm-Einstellungen im Bereich PHP › Debug, Abschnitt Xdebug. Hervorgehoben ist die deaktivierte Option „Force break at first line when a script is outside the project“.

Debugger starten und Path-Mapping einrichten

Xdebug auf dem Server haben wir ja schon aktiviert. Also können wir jetzt auch schon richtig starten.

PhpStorm muss auf die Xdebug-Verbindungen lauschen. Aktiviere dafür oben in der Titelleiste des PhpStorm-Fensters die Schaltfläche »Start listening for PHP Debug Connections«. (Sollte der Button bei dir nicht sichtbar sein, mache einen Rechtsklick auf die Titelleiste des Fensters und wähle »Customize Toolbar…« und füge die entsprechenden Schaltflächen hinzu.)

Screenshot der Schaltfläche zum Aktivieren des Lauschens auf Xdebug-Verbindungen. Das Icon ist kleiner Käfer mit einem roten x, das anzeigt, dass die Schaltfläche derzeit nicht aktiv ist.

Beim esten Ajax-Call, also normalerweise nach ein paar Sekunden, ploppt die erste Verbindung auf. Wenn dir das zu lange dauert, kannst du im Browser das Laden natürlich auch selber triggern in dem du die Seite neu lädst. Die erste Verbindung kann noch nicht zugeordnet werden. Das ist aber für’s Erste in Ordnung. Wir akzeptieren das erstmal.

Screenshot des Fensters »Incoming Connection From Xdebug« das erscheint, wenn die erste Verbindung erkannt wird. Hervorgehoben ist der Button »Akzeptieren« mit dem das Fenster bestätigt werden kann.

Das schöne daran ist: Dadurch wurde jetzt in den Einstellungen ein Server angelegt, bei dem Name, Host und Port schon richtig gesetzt sind. Für diesen Server müssen wir jetzt nur noch das richtige Path Mapping anlegen. Öffne dazu wieder die Einstellungen im Bereich PHP › Servers und wähle den Server aus, der hier angelegt wurde.

Screenshot der PhpStorm-Einstellungen im Bereich PHP-Servers. Es ist ein Server ausgewählt. Auf der rechten Seite sieht man die Einstellungen des Servers wie Host und Port. Die Option »Use path mappings« ist aktiv. Darunter sind die konfigurierten Pfade aufgelisted.

In der Liste der Pfade muss jetzt das Root-Verzeichnis von WordPress konfiguriert werden. Im DDEV-Container ist das unter /var/www/html, lokal natürlich da wo dein DDEV-Projekt halt nunmal liegt. Das sieht bei mir dann zum Beispiel so aus:

/Users/lukasfritze/LukasFritzeDev/WordPress/dev.site/wp-content/plugins/dev-plugin -> /var/www/html/wp-content/plugins/dev-plugin
/Users/lukasfritze/LukasFritzeDev/WordPress/dev.site -> /var/www/html

Jetzt fragst du dich vielleicht: Warum muss hier das Root-Verzeichnis und zusätzlich das Plugin-Verzeichnis explizit angegeben werden? Ist die spezifische Angabe des Plugin-Pfades nicht redundant? Ja, das stimmt. Allerdings gibt es da aus meiner Sicht grade einen Bug in PhpStorm durch den die Pfade nicht gespeichert wenn der einzige konfigurierte Pfad außerhalb des PhpStorm-Projektes liegt. Durch die doppelte Angabe wird alles richtig gespeichert. Es funktioniert auch ohne, aber unter Umständen muss dann nach einem Restart von PhpStorm die Konfiguration erneut vorgenommen werden und dass will man ja nicht ständig neu machen.

Breakpoints setzen

Ab jetzt können also Breakpoints gesetzt werden, PhpStorm lauscht auf Xdeubg-Verbindungen und hält dann an der richtigen Stelle an.

Screenshot einer einfach PHP-Plugin-Datei mit dem aktiven Debugger in PhpStorm. Unterhalb des Codes ist das Debug-Pannel mit den im Scope verfügbaren Variablen zu sehen.

Bonus-Tip: Conditional Breakpoints

In PhpStorm gibt es Conditional Breakpoints, also Breakpoints, die nur unter bestimmten Bedingungen die Ausführung des Programms tatsächlich anhalten. Ich nutze das im WordPress-Kontext gerne, um nicht von den regelmäßigen Ajax-Aufrufen genervt zu werden und diese zu ignorieren. Dafür einen Rechtsklick auf den bestehenden Breakpoint machen und die Bedingung in das entsprechende Feld eintragen, z.B. DOING_AJAX !== true. Andere Bedingungen können natürlich je nach Bedarf auch genutzt werden. Bei der nächsten Ajax-Verbindung triggert der Breakpoint dann nicht mehr.

Screenshot der Breakpoint-Einstellungen, unter anderem mit dem Feld »Condition« in das die erwähnte Bedingung eingetragen ist.

Und nicht vergessen XDebug in DDEV wieder zu deaktivieren, wenn man es nicht mehr braucht.