Accedi
IT

Fare il debug con Xdebug o PHP Debugger, a mano o con un'IA

L'IDE di JumPHP ha un vero debugger passo passo: si ferma il programma su una riga, si guardano le variabili, se ne cambia una e si avanza passo passo. Parla DBGp, il protocollo di Xdebug, e quindi può pilotare due motori:

  • Xdebug, il classico (predefinito);
  • PHP Debugger, un debugger DBGp più recente, libero e open source, compatibile con le impostazioni di Xdebug, con un sovraccarico quasi nullo.

Si usano allo stesso modo nell'IDE. Puoi anche affidare il debugger a un'IA (Claude Code): mette i punti di interruzione, avvia il programma, legge le variabili e trova da sola il bug.

Quale motore scegliere

Xdebug PHP Debugger
In JumPHP predefinito, tutti i runtime runtime desktop (PHP 8.2 - 8.5)
Sovraccarico PHP è nettamente più lento «near-zero overhead when idle», sempre attivo, nessun innesco da impostare
Runtime async (PHP 8.6, runtime: async) sì no: si usa Xdebug al suo posto (lo dice bin/jumphp)
IA il server MCP di JumPHP (bin/jumphp debug) il suo server MCP (dbgp mcp), che vede anche l'output dello script e gli avvisi di PHP

In pratica: PHP Debugger per l'uso quotidiano, le esecuzioni lunghe (un gioco che gira 600 fotogrammi, una suite di test) e il debug con IA. Xdebug se lavori con il runtime async (thread) o ti serve ciò che solo Xdebug fa. Sono intercambiabili nell'IDE: provali sullo stesso progetto.

La pagina di PHP Debugger non dà alcun numero di benchmark: afferma solo un costo quasi nullo finché non si fa debug. Misura sul tuo progetto se la differenza conta.

Scegliere il motore nell'IDE

  • Il pulsante Debug dell'intestazione (l'insetto accanto a Run, Maiusc+F9) apre un menu: Debug con (Xdebug o PHP Debugger, per questa esecuzione) e Motore predefinito (quello che un semplice clic userà da allora). Un clic destro sul pulsante apre lo stesso menu.
  • La prima esecuzione con un motore costruisce un'immagine Docker una volta (circa un minuto). Le successive partono subito.
  • Una notifica avvisa quando il programma non si collega mai al debugger (è terminato prima, o niente dopo 3 minuti). L'output della finestra Run di solito ne dice il motivo.

Scegliere il motore da un terminale

Tutto passa da bin/jumphp, come sempre:

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

# PHP Debugger
JUMPHP_DEBUGGER=php-debugger JUMPHP_XDEBUG=9003 bin/jumphp test pong
  • JUMPHP_XDEBUG=<porta> attiva il passo passo: PHP si collega a un debugger in ascolto su quella porta del tuo computer (composer, phpstan e php -l girano senza).
  • JUMPHP_DEBUGGER=xdebug|php-debugger sceglie il motore (xdebug per default).
  • Con php-debugger, bin/jumphp costruisce una volta l'immagine docker/desktop-phpdebugger, a partire da quella desktop, che resta senza.
  • Sul runtime async (PHP 8.6) compare il messaggio «PHP Debugger does not run on PHP 8.6 (async runtime): Xdebug is used» e gira Xdebug.

Fare il debug a mano nell'IDE

  1. Punto di interruzione: clicca nella barra laterale, a sinistra di una riga PHP. Un clic destro dà una condizione (un'espressione PHP: si ferma solo se è vera, es. $this->score < 0); Ctrl+F8 ne mette uno al cursore. I punti sono salvati per progetto e seguono le righe quando modifichi.
  2. Debug (Maiusc+F9): il programma gira e si ferma al primo punto. La riga è evidenziata e si apre la finestra Debug.
  3. Guardare: lo stack delle chiamate (clicca un frame per vedere le sue variabili), le variabili ad albero lette su richiesta, i watch e un campo per valutare qualsiasi espressione PHP dove il programma si è fermato.
  4. Cambiare un valore: doppio clic su una variabile o F2, scrivi un'espressione PHP (9, "Ada", [1, 2], null) e continua con il nuovo valore.
  5. Avanzare: Riprendi F9, Passo sopra F8, Passo dentro F7, Passo fuori Maiusc+F8, Esegui fino al cursore Alt+F9, Arresta.
  6. Eccezioni: Interrompi alle eccezioni… (l'icona di avviso della finestra Debug): * o nomi di classe (TypeError, App\GameOver). Si ferma dove l'eccezione è lanciata, catturata o no, e indica quale con il suo messaggio.

Ispettore al passaggio del mouse (nel prossimo aggiornamento dell'IDE): con il programma fermo a un punto di interruzione, passa il mouse su una variabile nell'editor per ottenere un albero espandibile del suo valore, con Copia e Modifica.

Un consiglio per i giochi: fai il debug di esecuzioni senza finestra (test, shot): un gioco fermo in una finestra si blocca finché non riprendi.

Fare il debug con un'IA

Un'IA fa il debug meglio con un debugger che con i var_dump(): legge i valori reali, una domanda alla volta, senza toccare il tuo codice. Esistono due server MCP. Usane uno alla volta (entrambi ascoltano sulla porta 9003).

1. Il server di JumPHP: bin/jumphp debug

Il debugger dell'IDE stesso come server MCP (gira in Docker, con Xdebug):

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

I suoi strumenti:

Strumento Cosa fa
debug_breakpoints imposta i punti di un file (lines, o {line, condition}), li elenca senza percorso, clear_all
debug_exceptions le eccezioni che fermano il programma (* = tutte, [] = nessuna)
debug_wait attende che il programma si fermi a un punto o a un'eccezione, poi dà dove, lo stack e le variabili
debug_state dove è fermo, lo stack, le variabili di un frame
debug_step step_over, step_into, step_out, run, stop: attende la fermata successiva
debug_run_to avanza fino a una riga
debug_eval valuta un'espressione PHP dove si è fermato
debug_variables le variabili di un frame, o i figli di una ($this->player, $list[3])
debug_set_value dà un nuovo valore a una variabile (un'espressione PHP)

I percorsi sono relativi al progetto. Claude avvia il programma da solo, in background, con JUMPHP_XDEBUG=9003, poi chiama debug_wait.

2. Il server di PHP Debugger: dbgp mcp

PHP Debugger fornisce il proprio server MCP in un piccolo programma, dbgp (licenza MIT; Linux e macOS, amd64 e arm64; Windows amd64).

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

# per questo progetto / per tutti i tuoi progetti
claude mcp add dbgp -- dbgp mcp
claude mcp add --scope user dbgp -- dbgp mcp

In Claude Code, /mcp mostra che è connesso. I suoi strumenti, con i nomi della documentazione di PHP Debugger:

  • connessione: status, listen, unlisten, sessions, wait_for_session, detach;
  • punti di interruzione: add_breakpoint, remove_breakpoint, breakpoints;
  • esecuzione: continue, wait_for_stop, stop;
  • guardare: stack, variables, variable, variable_value, source, output, warnings;
  • agire: eval, set_variable;
  • Docker / remoto: add_path_mapping, path_mappings.

Opzioni utili (dbgp mcp -h per tutte): -php-port PORTA (la porta a cui si collega PHP, 9003 per default), -mcp-port PORTA, -idekey CHIAVE, -map LOCALE=REMOTO (una corrispondenza di percorsi, ripetibile) e -no-eval, che vieta eval, set_variable e i punti condizionali: l'IA può solo guardare. Non nasconde i valori: password e chiavi restano visibili per lei.

Con bin/jumphp, JUMPHP_DEBUGGER=php-debugger bin/jumphp debug avvia dbgp mcp per te (serve dbgp installato sul tuo computer). Poi avvia il programma con lo stesso motore:

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

Una sessione di esempio

Tu, a Claude Code:

Il punteggio del gioco pong sale di 2 invece di 1 quando la palla supera la racchetta sinistra. Usa il debugger, non var_dump. Metti un punto di interruzione dove il punteggio aumenta (cerca in PlayScene), esegui bin/jumphp test pong con JUMPHP_XDEBUG=9003, fermati lì, leggi le variabili e dimmi perché. Correggi solo dopo avermi mostrato la causa.

Cosa fa allora l'IA, con gli strumenti sopra:

  1. trova la riga che aggiunge un punto e vi mette un punto di interruzione, con una condizione se la riga passa a ogni fotogramma ($this->ballX < 0);
  2. avvia il test in background e attende la fermata (debug_wait / wait_for_stop);
  3. legge $this->score, $this->scored e lo stack per vedere chi ha chiamato quella riga;
  4. esce una volta (debug_step step_out) per vedere il secondo chiamante: il punto è contato due volte;
  5. verifica la sua idea senza modificare nulla: dà un valore a $this->scored (debug_set_value / set_variable) e prosegue per vedere il punteggio restare giusto;
  6. solo allora modifica il codice e rilancia il test, senza punto di interruzione.

Consigli

  • Dillo chiaramente: «usa il debugger». Altrimenti un agente ripiega spesso su var_dump().
  • Dalle il comando che mostra il bug, ciò che ti aspetti e dove sospetti il problema.
  • Piccoli passi: qualche step_over, poi si guarda. Un punto condizionale ($enemy->hp <= 0) vale più di 600 fotogrammi passo passo.
  • Lasciala leggere le variabili e valutare espressioni: niente var_dump(), niente echo, nulla da ripulire dopo.
  • Preferisci le esecuzioni senza finestra (test, shot, php).
  • Segreti: l'IA vede tutte le variabili che legge (password, token, chiavi API). Fai il debug con dati di prova e usa -no-eval con dbgp se non vuoi che esegua codice nel tuo programma.
  • Non lasciare collegato il server MCP di un debugger in un progetto in cui non fai debug: toglilo con claude mcp remove.

Risoluzione dei problemi

Niente si ferma / «did not connect». Un debugger è in ascolto sulla porta (la finestra Debug dell'IDE o un server MCP)? Il programma deve essere avviato con JUMPHP_XDEBUG=<porta> e lo stesso motore di chi ascolta.

Porta già in uso. Due ascoltatori su 9003: l'IDE e bin/jumphp debug (o dbgp mcp), o due IDE. Fermane uno, o usa un'altra porta: JUMPHP_DEBUG_PORT=9010 bin/jumphp debug con JUMPHP_XDEBUG=9010, oppure dbgp -php-port 9010 mcp.

Il punto di interruzione non viene mai raggiunto. È su una riga senza codice (commento, riga vuota, parentesi di chiusura) o in un file che il programma non carica mai. Usa debug_state / guarda lo stack per vedere dov'è. Con -map o un IDE: i percorsi devono corrispondere (sotto).

Percorsi in Docker. bin/jumphp monta il tuo progetto in /workspace nel contenitore: il debugger dice file:///workspace/.... L'IDE e bin/jumphp debug lo associano da soli ai file del progetto, e i percorsi che dai sono relativi al progetto. Con dbgp mcp da solo, associa le cartelle: dbgp mcp -map /home/tu/progetto=/workspace.

PHP 8.6 (runtime async). PHP Debugger non gira lì: si usa Xdebug. Per usare PHP Debugger, fai il debug sul runtime predefinito (PHP 8.5) o togli runtime: async per la sessione.

Giochi nel browser. Il debugger lavora sul runtime desktop. Nel browser, riproduci il bug con bin/jumphp test o shot sul desktop.

Vedi anche Programmare, avviare e testare, Claude nell'IDE e IDE Remote.