Anmelden
DE

Debuggen mit Xdebug oder PHP Debugger, von Hand oder mit einer KI

Die JumPHP-IDE hat einen echten Schritt-für-Schritt-Debugger: Man hält das Programm in einer Zeile an, schaut sich die Variablen an, ändert eine und geht Schritt für Schritt weiter. Er spricht DBGp, das Protokoll von Xdebug, und kann deshalb zwei Engines steuern:

  • Xdebug, der Klassiker (Standard);
  • PHP Debugger, ein neuerer DBGp-Debugger, frei und Open Source, kompatibel mit den Einstellungen von Xdebug, mit nahezu null Overhead.

Beide bedient man in der IDE gleich. Den Debugger kannst du auch einer KI (Claude Code) überlassen: Sie setzt die Haltepunkte, startet das Programm, liest die Variablen und findet den Fehler selbst.

Welche Engine wählen

Xdebug PHP Debugger
In JumPHP Standard, alle Runtimes Desktop-Runtime (PHP 8.2 bis 8.5)
Overhead PHP läuft spürbar langsamer „near-zero overhead when idle“, immer aktiv, kein Auslöser nötig
Async-Runtime (PHP 8.6, runtime: async) ja nein: stattdessen wird Xdebug benutzt (bin/jumphp sagt es)
KI der MCP-Server von JumPHP (bin/jumphp debug) sein eigener MCP-Server (dbgp mcp), der auch die Ausgabe des Skripts und PHP-Warnungen sieht

In der Praxis: PHP Debugger für den Alltag, lange Läufe (ein Spiel, das 600 Bilder spielt, eine Testsuite) und Debugging mit KI. Xdebug, wenn du mit der Async-Runtime (Threads) arbeitest oder etwas brauchst, das nur Xdebug kann. In der IDE sind beide austauschbar: Probiere sie am selben Projekt aus.

Die Seite von PHP Debugger nennt keine Benchmark-Zahl: Sie behauptet nur Kosten nahe null, solange man nicht debuggt. Miss an deinem Projekt, wenn dir der Unterschied wichtig ist.

Die Engine in der IDE wählen

  • Der Knopf Debug in der Kopfzeile (der Käfer neben Run, Umschalt+F9) klappt ein Menü auf: Debuggen mit (Xdebug oder PHP Debugger, für diesen Start) und Standard-Engine (die, die ein einfacher Klick danach benutzt). Ein Rechtsklick auf den Knopf öffnet dasselbe Menü.
  • Der erste Start mit einer Engine baut einmal ein Docker-Image (etwa eine Minute). Spätere Starts sind sofort da.
  • Eine Benachrichtigung meldet, wenn sich das Programm nie mit dem Debugger verbindet (es war vorher zu Ende, oder nach 3 Minuten nichts). Die Ausgabe des Run-Fensters nennt oft den Grund.

Die Engine im Terminal wählen

Alles läuft wie immer über bin/jumphp:

# Xdebug (Standard)
JUMPHP_XDEBUG=9003 bin/jumphp test pong

# PHP Debugger
JUMPHP_DEBUGGER=php-debugger JUMPHP_XDEBUG=9003 bin/jumphp test pong
  • JUMPHP_XDEBUG=<Port> schaltet das Schrittdebugging ein: PHP verbindet sich mit einem Debugger, der auf diesem Port deines Computers lauscht (composer, phpstan und php -l laufen ohne ihn).
  • JUMPHP_DEBUGGER=xdebug|php-debugger wählt die Engine (Standard xdebug).
  • Mit php-debugger baut bin/jumphp einmal das Image docker/desktop-phpdebugger auf Basis des Desktop-Images, das ohne ihn bleibt.
  • Auf der Async-Runtime (PHP 8.6) erscheint die Meldung „PHP Debugger does not run on PHP 8.6 (async runtime): Xdebug is used“, und Xdebug läuft.

In der IDE von Hand debuggen

  1. Haltepunkt: Klicke in den Rand links neben einer PHP-Zeile. Ein Rechtsklick gibt eine Bedingung (ein PHP-Ausdruck: Er hält nur an, wenn er wahr ist, z. B. $this->score < 0); Strg+F8 setzt einen am Cursor. Haltepunkte werden pro Projekt gespeichert und folgen ihren Zeilen beim Bearbeiten.
  2. Debug (Umschalt+F9): Das Programm läuft und hält am ersten Haltepunkt an. Die Zeile wird markiert, das Fenster Debug öffnet sich.
  3. Ansehen: der Aufrufstapel (Klick auf einen Frame zeigt seine Variablen), die Variablen als Baum, bei Bedarf gelesen, Überwachungen (Watches) und ein Feld, um jeden PHP-Ausdruck dort auszuwerten, wo das Programm angehalten hat.
  4. Wert ändern: Doppelklick auf eine Variable oder F2, einen PHP-Ausdruck eingeben (9, "Ada", [1, 2], null) und mit dem neuen Wert weitermachen.
  5. Weitergehen: Fortsetzen F9, Prozedurschritt F8, Einzelschritt F7, Rücksprung Umschalt+F8, Ausführen bis Cursor Alt+F9, Stopp.
  6. Ausnahmen: Bei Ausnahmen anhalten… (das Warnsymbol des Debug-Fensters): * oder Klassennamen (TypeError, App\GameOver). Es hält dort an, wo die Ausnahme geworfen wird, gefangen oder nicht, und zeigt, welche, mit ihrer Meldung.

Inspektor beim Überfahren (im nächsten IDE-Update): Ist das Programm an einem Haltepunkt angehalten, fahre mit der Maus über eine Variable im Editor, um einen aufklappbaren Baum ihres Werts zu erhalten, mit Kopieren und Bearbeiten.

Ein Tipp für Spiele: Debugge Läufe ohne Fenster (test, shot): Ein in einem Fenster angehaltenes Spiel friert ein, bis du fortfährst.

Mit einer KI debuggen

Eine KI debuggt mit einem Debugger besser als mit var_dump(): Sie liest die echten Werte, eine Frage nach der anderen, ohne deinen Code zu ändern. Es gibt zwei MCP-Server. Benutze immer nur einen (beide lauschen auf Port 9003).

1. Der Server von JumPHP: bin/jumphp debug

Der Debugger der IDE selbst als MCP-Server (er läuft in Docker, mit Xdebug):

claude mcp add jumphp-debug -- bin/jumphp debug

Seine Werkzeuge:

Werkzeug Was es tut
debug_breakpoints setzt die Haltepunkte einer Datei (lines oder {line, condition}), listet sie ohne Pfad, clear_all
debug_exceptions die Ausnahmen, die das Programm anhalten (* = alle, [] = keine)
debug_wait wartet, bis das Programm an einem Haltepunkt oder einer Ausnahme anhält, und liefert wo, den Stapel und die Variablen
debug_state wo es angehalten ist, der Stapel, die Variablen eines Frames
debug_step step_over, step_into, step_out, run, stop: wartet auf den nächsten Halt
debug_run_to läuft bis zu einer Zeile
debug_eval wertet einen PHP-Ausdruck dort aus, wo es angehalten hat
debug_variables die Variablen eines Frames oder die Kinder einer davon ($this->player, $list[3])
debug_set_value gibt einer Variablen einen neuen Wert (ein PHP-Ausdruck)

Pfade sind relativ zum Projekt. Claude startet das Programm selbst im Hintergrund mit JUMPHP_XDEBUG=9003 und ruft dann debug_wait auf.

2. Der Server von PHP Debugger: dbgp mcp

PHP Debugger bringt seinen eigenen MCP-Server in einem kleinen Programm mit, dbgp (MIT-Lizenz; Linux und macOS, amd64 und arm64; Windows amd64).

# Installation (macOS / Linux)
curl -fsSL https://github.com/php-debugger/dbgp-client/releases/latest/download/install.sh | sh
dbgp -version

# für dieses Projekt / für alle deine Projekte
claude mcp add dbgp -- dbgp mcp
claude mcp add --scope user dbgp -- dbgp mcp

In Claude Code zeigt /mcp, dass er verbunden ist. Seine Werkzeuge, unter den Namen der Dokumentation von PHP Debugger:

  • Verbindung: status, listen, unlisten, sessions, wait_for_session, detach;
  • Haltepunkte: add_breakpoint, remove_breakpoint, breakpoints;
  • Ausführung: continue, wait_for_stop, stop;
  • Ansehen: stack, variables, variable, variable_value, source, output, warnings;
  • Handeln: eval, set_variable;
  • Docker / entfernt: add_path_mapping, path_mappings.

Nützliche Optionen (dbgp mcp -h für alle): -php-port PORT (der Port, mit dem sich PHP verbindet, Standard 9003), -mcp-port PORT, -idekey SCHLÜSSEL, -map LOKAL=ENTFERNT (eine Pfadzuordnung, wiederholbar) und -no-eval, das eval, set_variable und bedingte Haltepunkte verbietet: Die KI kann nur ansehen. Es versteckt die Werte nicht: Passwörter und Schlüssel bleiben für sie sichtbar.

Über bin/jumphp startet JUMPHP_DEBUGGER=php-debugger bin/jumphp debug für dich dbgp mcp (dbgp muss auf deinem Computer installiert sein). Starte das Programm dann mit derselben Engine:

JUMPHP_DEBUGGER=php-debugger JUMPHP_XDEBUG=9003 bin/jumphp test pong

Eine Beispielsitzung

Du, an Claude Code:

Der Punktestand des Spiels pong steigt um 2 statt um 1, wenn der Ball den linken Schläger passiert. Benutze den Debugger, nicht var_dump. Setze einen Haltepunkt dort, wo der Punktestand erhöht wird (suche in PlayScene), starte bin/jumphp test pong mit JUMPHP_XDEBUG=9003, halte dort an, lies die Variablen und sag mir, warum. Korrigiere erst, nachdem du mir die Ursache gezeigt hast.

Was die KI dann mit den obigen Werkzeugen tut:

  1. findet die Zeile, die einen Punkt addiert, und setzt dort einen Haltepunkt, mit einer Bedingung, wenn die Zeile in jedem Bild läuft ($this->ballX < 0);
  2. startet den Test im Hintergrund und wartet auf den Halt (debug_wait / wait_for_stop);
  3. liest $this->score, $this->scored und den Stapel, um zu sehen, wer diese Zeile aufgerufen hat;
  4. geht einmal heraus (debug_step step_out), um den zweiten Aufrufer zu sehen: Der Punkt wird doppelt gezählt;
  5. prüft ihre Idee, ohne etwas zu ändern: Sie gibt $this->scored einen Wert (debug_set_value / set_variable) und läuft weiter, um zu sehen, dass der Punktestand stimmt;
  6. erst dann ändert sie den Code und startet den Test erneut, ohne Haltepunkt.

Tipps

  • Sag es klar: „benutze den Debugger“. Sonst fällt ein Agent oft auf var_dump() zurück.
  • Gib ihr den Befehl, der den Fehler zeigt, was du erwartest und wo du ihn vermutest.
  • Kleine Schritte: ein paar step_over, dann ansehen. Ein bedingter Haltepunkt ($enemy->hp <= 0) ist besser als 600 Bilder Schritt für Schritt.
  • Lass sie Variablen lesen und Ausdrücke auswerten: kein var_dump(), kein echo, nichts aufzuräumen.
  • Bevorzuge Läufe ohne Fenster (test, shot, php).
  • Geheimnisse: Die KI sieht jede Variable, die sie liest (Passwörter, Tokens, API-Schlüssel). Debugge mit Testdaten und benutze -no-eval mit dbgp, wenn sie keinen Code in deinem Programm ausführen soll.
  • Lass den MCP-Server eines Debuggers nicht in einem Projekt verbunden, in dem du nicht debuggst: Entferne ihn mit claude mcp remove.

Fehlerbehebung

Nichts hält an / „did not connect“. Lauscht ein Debugger auf dem Port (das Debug-Fenster der IDE oder ein MCP-Server)? Das Programm muss mit JUMPHP_XDEBUG=<Port> und derselben Engine gestartet werden wie der Zuhörer.

Port schon belegt. Zwei Zuhörer auf 9003: die IDE und bin/jumphp debug (oder dbgp mcp), oder zwei IDEs. Beende einen oder nimm einen anderen Port: JUMPHP_DEBUG_PORT=9010 bin/jumphp debug mit JUMPHP_XDEBUG=9010, oder dbgp -php-port 9010 mcp.

Der Haltepunkt wird nie erreicht. Er liegt auf einer Zeile ohne Code (Kommentar, Leerzeile, schließende Klammer) oder in einer Datei, die das Programm nie lädt. Nutze debug_state / sieh dir den Stapel an. Mit -map oder einer IDE müssen die Pfade übereinstimmen (unten).

Pfade in Docker. bin/jumphp bindet dein Projekt unter /workspace im Container ein: Der Debugger sagt file:///workspace/.... Die IDE und bin/jumphp debug ordnen das selbst den Dateien des Projekts zu, und die Pfade, die du angibst, sind relativ zum Projekt. Mit dbgp mcp allein ordne die Ordner zu: dbgp mcp -map /home/du/projekt=/workspace.

PHP 8.6 (Async-Runtime). PHP Debugger läuft dort nicht: Xdebug wird benutzt. Um PHP Debugger zu nutzen, debugge auf der Standard-Runtime (PHP 8.5) oder entferne runtime: async für die Sitzung.

Spiele im Browser. Der Debugger arbeitet auf der Desktop-Runtime. Reproduziere den Fehler im Browser mit bin/jumphp test oder shot auf dem Desktop.

Siehe auch Programmieren, starten und testen, Claude in der IDE und IDE Remote.