Inloggen
NL

Debuggen met Xdebug of PHP Debugger, met de hand of met een AI

De JumPHP-IDE heeft een echte stap-voor-stap-debugger: je zet het programma stil op een regel, bekijkt de variabelen, wijzigt er een en gaat stap voor stap verder. Hij spreekt DBGp, het protocol van Xdebug, en kan dus twee engines aansturen:

  • Xdebug, de klassieker (standaard);
  • PHP Debugger, een nieuwere DBGp-debugger, vrij en open source, compatibel met de instellingen van Xdebug, met vrijwel geen overhead.

Beide gebruik je in de IDE op dezelfde manier. Je kunt de debugger ook aan een AI (Claude Code) geven: die zet de breekpunten, start het programma, leest de variabelen en vindt de bug zelf.

Welke engine kiezen

Xdebug PHP Debugger
In JumPHP standaard, alle runtimes desktop-runtime (PHP 8.2 tot 8.5)
Overhead PHP draait merkbaar trager „near-zero overhead when idle”, altijd actief, geen trigger in te stellen
Async-runtime (PHP 8.6, runtime: async) ja nee: Xdebug wordt gebruikt (bin/jumphp zegt het)
AI de MCP-server van JumPHP (bin/jumphp debug) zijn eigen MCP-server (dbgp mcp), die ook de uitvoer van het script en PHP-waarschuwingen ziet

In de praktijk: PHP Debugger voor dagelijks gebruik, lange runs (een spel dat 600 beelden speelt, een testsuite) en debuggen met AI. Xdebug als je met de async-runtime (threads) werkt of iets nodig hebt dat alleen Xdebug doet. In de IDE zijn ze uitwisselbaar: probeer ze op hetzelfde project.

De pagina van PHP Debugger geeft geen benchmarkcijfer: ze stelt alleen dat het vrijwel niets kost zolang je niet debugt. Meet op je eigen project als het verschil voor je telt.

De engine kiezen in de IDE

  • De knop Debug in de kop (de kever naast Run, Shift+F9) klapt een menu open: Debuggen met (Xdebug of PHP Debugger, voor deze run) en Standaardengine (degene die een gewone klik daarna gebruikt). Een rechtsklik op de knop opent hetzelfde menu.
  • De eerste run met een engine bouwt eenmalig een Docker-image (ongeveer een minuut). Latere runs starten meteen.
  • Een melding waarschuwt als het programma nooit verbinding maakt met de debugger (het was eerder klaar, of na 3 minuten niets). De uitvoer van het Run-venster geeft vaak de reden.

De engine kiezen vanuit een terminal

Alles loopt zoals altijd via bin/jumphp:

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

# PHP Debugger
JUMPHP_DEBUGGER=php-debugger JUMPHP_XDEBUG=9003 bin/jumphp test pong
  • JUMPHP_XDEBUG=<poort> zet stap-voor-stap-debuggen aan: PHP verbindt met een debugger die op die poort van je computer luistert (composer, phpstan en php -l draaien zonder).
  • JUMPHP_DEBUGGER=xdebug|php-debugger kiest de engine (standaard xdebug).
  • Met php-debugger bouwt bin/jumphp eenmalig de image docker/desktop-phpdebugger, op basis van de desktop-image, die er zelf zonder blijft.
  • Op de async-runtime (PHP 8.6) verschijnt de melding „PHP Debugger does not run on PHP 8.6 (async runtime): Xdebug is used” en draait Xdebug.

Met de hand debuggen in de IDE

  1. Breekpunt: klik in de goot links van een PHP-regel. Een rechtsklik geeft een voorwaarde (een PHP-expressie: hij stopt alleen als die waar is, bv. $this->score < 0); Ctrl+F8 zet er een bij de cursor. Breekpunten worden per project bewaard en volgen hun regels als je bewerkt.
  2. Debug (Shift+F9): het programma draait en stopt bij het eerste breekpunt. De regel wordt gemarkeerd en het venster Debug opent.
  3. Kijken: de aanroepstack (klik op een frame om zijn variabelen te zien), de variabelen als boom, op verzoek gelezen, watches en een veld om elke PHP-expressie te evalueren waar het programma stopte.
  4. Een waarde wijzigen: dubbelklik op een variabele of F2, typ een PHP-expressie (9, "Ada", [1, 2], null) en ga verder met de nieuwe waarde.
  5. Verder gaan: Hervatten F9, Stap over F8, Stap in F7, Stap uit Shift+F8, Uitvoeren tot cursor Alt+F9, Stoppen.
  6. Uitzonderingen: Stoppen bij uitzonderingen… (het waarschuwingsicoon van het Debug-venster): * of klassenamen (TypeError, App\GameOver). Hij stopt waar de uitzondering wordt gegooid, opgevangen of niet, en toont welke met haar bericht.

Inspector bij muisaanwijzing (in de volgende IDE-update): staat het programma stil op een breekpunt, beweeg dan de muis over een variabele in de editor voor een uitklapbare boom van haar waarde, met Kopiëren en Bewerken.

Een tip voor spellen: debug runs zonder venster (test, shot): een spel dat in een venster stilstaat, bevriest tot je doorgaat.

Debuggen met een AI

Een AI debugt beter met een debugger dan met var_dump(): ze leest de echte waarden, één vraag tegelijk, zonder je code te wijzigen. Er zijn twee MCP-servers. Gebruik er telkens één (beide luisteren op poort 9003).

1. De server van JumPHP: bin/jumphp debug

De debugger van de IDE zelf als MCP-server (draait in Docker, met Xdebug):

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

Zijn tools:

Tool Wat ze doet
debug_breakpoints zet de breekpunten van een bestand (lines, of {line, condition}), toont ze zonder pad, clear_all
debug_exceptions de uitzonderingen die het programma stoppen (* = alle, [] = geen)
debug_wait wacht tot het programma stopt op een breekpunt of uitzondering, en geeft waar, de stack en de variabelen
debug_state waar het stilstaat, de stack, de variabelen van een frame
debug_step step_over, step_into, step_out, run, stop: wacht op de volgende stop
debug_run_to loopt door tot een regel
debug_eval evalueert een PHP-expressie waar het stopte
debug_variables de variabelen van een frame, of de kinderen van een ervan ($this->player, $list[3])
debug_set_value geeft een variabele een nieuwe waarde (een PHP-expressie)

Paden zijn relatief aan het project. Claude start het programma zelf op de achtergrond met JUMPHP_XDEBUG=9003 en roept dan debug_wait aan.

2. De server van PHP Debugger: dbgp mcp

PHP Debugger levert zijn eigen MCP-server in een klein programma, dbgp (MIT-licentie; Linux en macOS, amd64 en arm64; Windows amd64).

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

# voor dit project / voor al je projecten
claude mcp add dbgp -- dbgp mcp
claude mcp add --scope user dbgp -- dbgp mcp

In Claude Code toont /mcp dat hij verbonden is. Zijn tools, onder de namen uit de documentatie van PHP Debugger:

  • verbinding: status, listen, unlisten, sessions, wait_for_session, detach;
  • breekpunten: add_breakpoint, remove_breakpoint, breakpoints;
  • uitvoeren: continue, wait_for_stop, stop;
  • kijken: stack, variables, variable, variable_value, source, output, warnings;
  • handelen: eval, set_variable;
  • Docker / extern: add_path_mapping, path_mappings.

Handige opties (dbgp mcp -h voor alle): -php-port POORT (de poort waarmee PHP verbindt, standaard 9003), -mcp-port POORT, -idekey SLEUTEL, -map LOKAAL=EXTERN (een padkoppeling, herhaalbaar) en -no-eval, dat eval, set_variable en voorwaardelijke breekpunten verbiedt: de AI kan alleen kijken. Het verbergt de waarden niet: wachtwoorden en sleutels blijven voor haar zichtbaar.

Via bin/jumphp start JUMPHP_DEBUGGER=php-debugger bin/jumphp debug dbgp mcp voor je (dbgp moet op je computer geïnstalleerd zijn). Start het programma daarna met dezelfde engine:

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

Een voorbeeldsessie

Jij, aan Claude Code:

De score van het spel pong stijgt met 2 in plaats van 1 als de bal het linkerbat passeert. Gebruik de debugger, geen var_dump. Zet een breekpunt waar de score omhooggaat (zoek in PlayScene), voer bin/jumphp test pong uit met JUMPHP_XDEBUG=9003, stop daar, lees de variabelen en zeg me waarom. Repareer pas nadat je me de oorzaak hebt laten zien.

Wat de AI dan doet, met de tools hierboven:

  1. vindt de regel die een punt optelt en zet daar een breekpunt, met een voorwaarde als de regel elk beeld loopt ($this->ballX < 0);
  2. start de test op de achtergrond en wacht op de stop (debug_wait / wait_for_stop);
  3. leest $this->score, $this->scored en de stack om te zien wie deze regel aanriep;
  4. stapt één keer uit (debug_step step_out) om de tweede aanroeper te zien: het punt wordt dubbel geteld;
  5. controleert haar idee zonder iets te wijzigen: ze geeft $this->scored een waarde (debug_set_value / set_variable) en gaat door om de score juist te zien blijven;
  6. pas dan wijzigt ze de code en draait de test opnieuw, zonder breekpunt.

Tips

  • Zeg het duidelijk: „gebruik de debugger”. Anders valt een agent vaak terug op var_dump().
  • Geef haar het commando dat de bug toont, wat je verwacht en waar je het vermoedt.
  • Kleine stappen: een paar step_over, dan kijken. Een voorwaardelijk breekpunt ($enemy->hp <= 0) is beter dan 600 beelden stap voor stap.
  • Laat haar variabelen lezen en expressies evalueren: geen var_dump(), geen echo, niets om achteraf op te ruimen.
  • Geef de voorkeur aan runs zonder venster (test, shot, php).
  • Geheimen: de AI ziet elke variabele die ze leest (wachtwoorden, tokens, API-sleutels). Debug met testgegevens en gebruik -no-eval met dbgp als je niet wilt dat ze code in je programma uitvoert.
  • Laat de MCP-server van een debugger niet verbonden in een project waarin je niet debugt: verwijder hem met claude mcp remove.

Problemen oplossen

Niets stopt / „did not connect”. Luistert er een debugger op de poort (het Debug-venster van de IDE of een MCP-server)? Het programma moet gestart worden met JUMPHP_XDEBUG=<poort> en dezelfde engine als de luisteraar.

Poort al in gebruik. Twee luisteraars op 9003: de IDE en bin/jumphp debug (of dbgp mcp), of twee IDE's. Stop er een, of gebruik een andere poort: JUMPHP_DEBUG_PORT=9010 bin/jumphp debug met JUMPHP_XDEBUG=9010, of dbgp -php-port 9010 mcp.

Het breekpunt wordt nooit bereikt. Het staat op een regel zonder code (commentaar, lege regel, sluitende accolade) of in een bestand dat het programma nooit laadt. Gebruik debug_state / bekijk de stack om te zien waar het staat. Met -map of een IDE moeten de paden overeenkomen (hieronder).

Paden in Docker. bin/jumphp koppelt je project onder /workspace in de container: de debugger zegt file:///workspace/.... De IDE en bin/jumphp debug koppelen dat zelf aan de bestanden van het project, en de paden die je geeft zijn relatief aan het project. Met dbgp mcp alleen koppel je de mappen: dbgp mcp -map /home/jij/project=/workspace.

PHP 8.6 (async-runtime). PHP Debugger draait daar niet: Xdebug wordt gebruikt. Wil je PHP Debugger gebruiken, debug dan op de standaardruntime (PHP 8.5) of verwijder runtime: async voor de sessie.

Spellen in de browser. De debugger werkt op de desktop-runtime. Reproduceer in de browser de bug met bin/jumphp test of shot op de desktop.

Zie ook Programmeren, starten en testen, Claude in de IDE en IDE Remote.