Entrar
PT

Depurar com Xdebug ou PHP Debugger, à mão ou com uma IA

O IDE do JumPHP tem um verdadeiro depurador passo a passo: pára-se o programa numa linha, veem-se as variáveis, muda-se uma e avança-se passo a passo. Fala DBGp, o protocolo do Xdebug, e por isso pode comandar dois motores:

  • Xdebug, o clássico (por defeito);
  • PHP Debugger, um depurador DBGp mais recente, livre e de código aberto, compatível com as definições do Xdebug, com sobrecarga quase nula.

Os dois usam-se da mesma maneira no IDE. Também podes confiar o depurador a uma IA (Claude Code): ela põe os pontos de paragem, executa o programa, lê as variáveis e encontra o erro sozinha.

Que motor escolher

Xdebug PHP Debugger
No JumPHP por defeito, todos os runtimes runtime de secretária (PHP 8.2 a 8.5)
Sobrecarga o PHP fica claramente mais lento «near-zero overhead when idle», sempre ativo, sem gatilho a configurar
Runtime async (PHP 8.6, runtime: async) sim não: usa-se o Xdebug (o bin/jumphp di-lo)
IA o servidor MCP do JumPHP (bin/jumphp debug) o seu servidor MCP (dbgp mcp), que também vê a saída do script e os avisos do PHP

Na prática: PHP Debugger para o dia a dia, execuções longas (um jogo que joga 600 imagens, uma suite de testes) e depuração com IA. Xdebug se trabalhas com o runtime async (threads) ou precisas do que só o Xdebug faz. São intermutáveis no IDE: experimenta-os no mesmo projeto.

A página do PHP Debugger não dá nenhum número de benchmark: afirma só um custo quase nulo enquanto não se depura. Mede no teu projeto se a diferença te interessa.

Escolher o motor no IDE

  • O botão Debug do cabeçalho (o bicho ao lado de Run, Shift+F9) abre um menu: Depurar com (Xdebug ou PHP Debugger, para esta execução) e Motor padrão (o que um simples clique usará daí em diante). Um clique direito no botão abre o mesmo menu.
  • A primeira execução com um motor constrói uma imagem Docker uma só vez (cerca de um minuto). As seguintes arrancam logo.
  • Uma notificação avisa quando o programa nunca se liga ao depurador (terminou antes, ou nada após 3 minutos). A saída da janela Run costuma dizer porquê.

Escolher o motor a partir de um terminal

Tudo passa pelo bin/jumphp, como sempre:

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

# PHP Debugger
JUMPHP_DEBUGGER=php-debugger JUMPHP_XDEBUG=9003 bin/jumphp test pong
  • JUMPHP_XDEBUG=<porta> ativa o passo a passo: o PHP liga-se a um depurador que escuta nessa porta do teu computador (composer, phpstan e php -l correm sem ele).
  • JUMPHP_DEBUGGER=xdebug|php-debugger escolhe o motor (xdebug por defeito).
  • Com php-debugger, o bin/jumphp constrói uma vez a imagem docker/desktop-phpdebugger, a partir da imagem de secretária, que fica sem ele.
  • No runtime async (PHP 8.6) aparece a mensagem «PHP Debugger does not run on PHP 8.6 (async runtime): Xdebug is used» e corre o Xdebug.

Depurar à mão no IDE

  1. Ponto de paragem: clica na margem, à esquerda de uma linha de PHP. Um clique direito dá uma condição (uma expressão PHP: só pára se for verdadeira, p. ex. $this->score < 0); Ctrl+F8 põe um no cursor. Os pontos são guardados por projeto e seguem as suas linhas quando editas.
  2. Debug (Shift+F9): o programa corre e pára no primeiro ponto. A linha fica marcada e abre-se a janela Debug.
  3. Ver: a pilha de chamadas (clica numa moldura para ver as suas variáveis), as variáveis em árvore lidas a pedido, as vigilâncias (watches) e um campo para avaliar qualquer expressão PHP onde o programa parou.
  4. Mudar um valor: duplo clique numa variável ou F2, escreve uma expressão PHP (9, "Ada", [1, 2], null) e continua com o novo valor.
  5. Avançar: Retomar F9, Passo por cima F8, Passo para dentro F7, Passo para fora Shift+F8, Executar até o cursor Alt+F9, Parar.
  6. Exceções: Parar nas exceções… (o ícone de aviso da janela Debug): * ou nomes de classes (TypeError, App\GameOver). Pára onde a exceção é lançada, apanhada ou não, e indica qual com a sua mensagem.

Inspetor ao passar o rato (na próxima atualização do IDE): com o programa parado num ponto de paragem, passa o rato sobre uma variável no editor para obter uma árvore expansível do seu valor, com Copiar e Editar.

Uma dica para os jogos: depura execuções sem janela (test, shot): um jogo parado numa janela congela até continuares.

Depurar com uma IA

Uma IA depura melhor com um depurador do que com var_dump(): lê os valores reais, uma pergunta de cada vez, sem tocar no teu código. Há dois servidores MCP. Usa um de cada vez (os dois escutam na porta 9003).

1. O servidor do JumPHP: bin/jumphp debug

O depurador do próprio IDE como servidor MCP (corre no Docker, com Xdebug):

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

As suas ferramentas:

Ferramenta O que faz
debug_breakpoints define os pontos de um ficheiro (lines, ou {line, condition}), lista-os sem caminho, clear_all
debug_exceptions as exceções que param o programa (* = todas, [] = nenhuma)
debug_wait espera que o programa pare num ponto ou numa exceção, e dá onde, a pilha e as variáveis
debug_state onde está parado, a pilha, as variáveis de uma moldura
debug_step step_over, step_into, step_out, run, stop: espera a paragem seguinte
debug_run_to avança até uma linha
debug_eval avalia uma expressão PHP onde parou
debug_variables as variáveis de uma moldura, ou os filhos de uma ($this->player, $list[3])
debug_set_value dá um novo valor a uma variável (uma expressão PHP)

Os caminhos são relativos ao projeto. O Claude lança o programa ele próprio, em segundo plano, com JUMPHP_XDEBUG=9003, e depois chama debug_wait.

2. O servidor do PHP Debugger: dbgp mcp

O PHP Debugger traz o seu próprio servidor MCP num pequeno programa, dbgp (licença MIT; Linux e macOS, amd64 e arm64; Windows amd64).

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

# para este projeto / para todos os teus projetos
claude mcp add dbgp -- dbgp mcp
claude mcp add --scope user dbgp -- dbgp mcp

No Claude Code, /mcp mostra que está ligado. As suas ferramentas, com os nomes da documentação do PHP Debugger:

  • ligação: status, listen, unlisten, sessions, wait_for_session, detach;
  • pontos de paragem: add_breakpoint, remove_breakpoint, breakpoints;
  • execução: continue, wait_for_stop, stop;
  • ver: stack, variables, variable, variable_value, source, output, warnings;
  • agir: eval, set_variable;
  • Docker / remoto: add_path_mapping, path_mappings.

Opções úteis (dbgp mcp -h para todas): -php-port PORTA (a porta a que o PHP se liga, 9003 por defeito), -mcp-port PORTA, -idekey CHAVE, -map LOCAL=REMOTO (uma correspondência de caminhos, repetível) e -no-eval, que proíbe eval, set_variable e os pontos condicionais: a IA só pode olhar. Não esconde os valores: palavras-passe e chaves continuam visíveis para ela.

Pelo bin/jumphp, JUMPHP_DEBUGGER=php-debugger bin/jumphp debug lança o dbgp mcp por ti (precisa do dbgp instalado no teu computador). Depois lança o programa com o mesmo motor:

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

Uma sessão de exemplo

Tu, ao Claude Code:

A pontuação do jogo pong sobe 2 em vez de 1 quando a bola passa a raquete da esquerda. Usa o depurador, não o var_dump. Põe um ponto de paragem onde a pontuação aumenta (procura em PlayScene), executa bin/jumphp test pong com JUMPHP_XDEBUG=9003, pára aí, lê as variáveis e diz-me porquê. Corrige só depois de me mostrares a causa.

O que a IA faz então, com as ferramentas acima:

  1. encontra a linha que soma um ponto e põe lá um ponto de paragem, com uma condição se a linha passa a cada imagem ($this->ballX < 0);
  2. lança o teste em segundo plano e espera a paragem (debug_wait / wait_for_stop);
  3. lê $this->score, $this->scored e a pilha para ver quem chamou essa linha;
  4. sai uma vez (debug_step step_out) para ver o segundo chamador: o ponto é contado duas vezes;
  5. verifica a sua ideia sem editar nada: dá um valor a $this->scored (debug_set_value / set_variable) e continua para ver a pontuação ficar certa;
  6. só então edita o código e repete o teste, sem ponto de paragem.

Dicas

  • Diz claramente: «usa o depurador». Senão, um agente volta muitas vezes ao var_dump().
  • Dá-lhe o comando que mostra o erro, o que esperas e onde suspeitas.
  • Passos pequenos: uns step_over, depois olha-se. Um ponto condicional ($enemy->hp <= 0) vale mais do que 600 imagens passo a passo.
  • Deixa-a ler variáveis e avaliar expressões: sem var_dump(), sem echo, nada a limpar depois.
  • Prefere as execuções sem janela (test, shot, php).
  • Segredos: a IA vê todas as variáveis que lê (palavras-passe, tokens, chaves de API). Depura com dados de teste e usa -no-eval com o dbgp se não queres que execute código no teu programa.
  • Não deixes ligado o servidor MCP de um depurador num projeto onde não depuras: tira-o com claude mcp remove.

Resolução de problemas

Nada pára / «did not connect». Há um depurador a escutar na porta (a janela Debug do IDE ou um servidor MCP)? O programa tem de ser lançado com JUMPHP_XDEBUG=<porta> e o mesmo motor de quem escuta.

Porta já em uso. Dois ouvintes em 9003: o IDE e bin/jumphp debug (ou dbgp mcp), ou dois IDE. Pára um, ou usa outra porta: JUMPHP_DEBUG_PORT=9010 bin/jumphp debug com JUMPHP_XDEBUG=9010, ou dbgp -php-port 9010 mcp.

O ponto de paragem nunca é atingido. Está numa linha sem código (comentário, linha vazia, chaveta de fecho) ou num ficheiro que o programa nunca carrega. Usa debug_state / vê a pilha para saber onde está. Com -map ou um IDE: os caminhos têm de coincidir (abaixo).

Caminhos no Docker. O bin/jumphp monta o teu projeto em /workspace no contentor: o depurador diz file:///workspace/.... O IDE e o bin/jumphp debug associam isso sozinhos aos ficheiros do projeto, e os caminhos que dás são relativos ao projeto. Com o dbgp mcp sozinho, associa as pastas: dbgp mcp -map /home/tu/projeto=/workspace.

PHP 8.6 (runtime async). O PHP Debugger não corre aí: usa-se o Xdebug. Para usar o PHP Debugger, depura no runtime por defeito (PHP 8.5) ou tira runtime: async durante a sessão.

Jogos no navegador. O depurador trabalha no runtime de secretária. No navegador, reproduz o erro com bin/jumphp test ou shot na secretária.

Veja também Programar, iniciar e testar, Claude no IDE e IDE Remote.