PL

Debugowanie z Xdebug lub PHP Debugger, ręcznie albo z AI

JumPHP IDE ma prawdziwy debugger krokowy: zatrzymujesz program na linii, oglądasz zmienne, zmieniasz jedną z nich i idziesz dalej krok po kroku. Mówi on DBGp, protokołem Xdebug, więc może obsługiwać dwa silniki:

  • Xdebug, klasyczny (domyślny);
  • PHP Debugger, nowszy debugger DBGp, darmowy i open source, zgodny z ustawieniami Xdebug, z narzutem bliskim zeru.

W IDE oba działają tak samo. Debugger możesz też oddać AI (Claude Code): sam ustawia punkty przerwania, uruchamia program, czyta zmienne i znajduje błąd.

Który silnik wybrać

Xdebug PHP Debugger
W JumPHP domyślny, wszystkie runtime'y runtime desktopowy (PHP 8.2 do 8.5)
Narzut PHP działa wyraźnie wolniej „near-zero overhead when idle", zawsze włączony, bez wyzwalacza
Runtime async (PHP 8.6, runtime: async) tak nie: używany jest Xdebug, a IDE o tym informuje
AI serwer MCP JumPHP (bin/jumphp debug) własny serwer MCP (dbgp mcp), który widzi też wyjście skryptu i ostrzeżenia PHP

W praktyce: wybierz PHP Debugger do codziennego debugowania, długich uruchomień (gra grająca 600 klatek, zestaw testów) i debugowania z AI. Zostań przy Xdebug, jeśli pracujesz z runtime async (wątki) lub potrzebujesz czegoś, co potrafi tylko Xdebug. W IDE oba są wymienne, więc możesz wypróbować oba na tym samym projekcie.

Strona PHP Debuggera nie podaje żadnych wyników pomiarów: stwierdza tylko, że koszt jest bliski zeru, dopóki nie debugujesz. Jeśli różnica ma dla ciebie znaczenie, zmierz ją na własnym projekcie.

Wybór silnika w IDE

  • Przycisk Debuguj w nagłówku (robak obok Uruchom, Shift+F9) rozwija menu: Debuguj za pomocą (Xdebug lub PHP Debugger, dla tego uruchomienia) i Silnik domyślny (silnik używany odtąd przy zwykłym kliknięciu). Kliknięcie prawym przyciskiem otwiera to samo menu.
  • Pierwsze uruchomienie z danym silnikiem buduje obraz Dockera (około minuty). Kolejne startują od razu.
  • Powiadomienie informuje, gdy program nigdy nie połączył się z debuggerem (zakończył się wcześniej albo nic po 3 minutach). Powód zwykle widać w wyjściu okna Uruchom.

Wybór silnika z terminala

Wszystko idzie przez bin/jumphp, jak zawsze:

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

# PHP Debugger
JUMPHP_DEBUGGER=php-debugger JUMPHP_XDEBUG=9003 bin/jumphp test pong
  • JUMPHP_XDEBUG=<port> włącza debugowanie krokowe: PHP łączy się z debuggerem nasłuchującym na tym porcie twojego komputera (composer, phpstan i php -l działają bez niego).
  • JUMPHP_DEBUGGER=xdebug|php-debugger wybiera silnik (domyślnie xdebug).
  • Z php-debugger bin/jumphp buduje jednorazowo obraz docker/desktop-phpdebugger na bazie obrazu desktopowego, który pozostaje bez niego.
  • Na runtime async (PHP 8.6) wyświetlany jest komunikat „PHP Debugger does not run on PHP 8.6 (async runtime): Xdebug is used" i działa Xdebug.

Debugowanie ręczne w IDE

  1. Punkt przerwania: kliknij w rynnę po lewej stronie linii PHP. Prawy przycisk pozwala ustawić warunek (wyrażenie PHP: zatrzymanie tylko gdy prawdziwe, np. $this->score < 0); Ctrl+F8 ustawia punkt przy kursorze. Punkty przerwania są zapamiętywane dla projektu i podążają za swoimi liniami podczas edycji.
  2. Debuguj (Shift+F9): program działa i zatrzymuje się na pierwszym punkcie przerwania. Linia jest zaznaczona i otwiera się okno narzędzia Debug.
  3. Oglądaj: stos wywołań (kliknij ramkę, by zobaczyć jej zmienne), zmienne jako drzewo czytane na żądanie, watches i pole do obliczania dowolnego wyrażenia PHP w miejscu zatrzymania.
  4. Zmiana wartości: dwuklik na zmiennej lub F2, wpisz wyrażenie PHP (9, "Ada", [1, 2], null) i kontynuuj z nową wartością.
  5. Poruszanie się: Wznów F9, Krok przez F8, Krok do wnętrza F7, Krok na zewnątrz Shift+F8, Uruchom do kursora Alt+F9, Zatrzymaj.
  6. Wyjątki: Zatrzymuj na wyjątkach… (ikona ostrzeżenia w oknie Debug): * lub nazwy klas (TypeError, App\GameOver). Zatrzymuje się tam, gdzie wyjątek jest rzucany, złapany czy nie, i pokazuje który, wraz z komunikatem.

Inspektor po najechaniu myszą (w następnej aktualizacji IDE): gdy program jest zatrzymany na punkcie przerwania, najedź myszą na zmienną w edytorze, by zobaczyć rozwijane drzewo jej wartości z przyciskami Copy i Edit.

Wskazówka dla gier: debuguj uruchomienia headless (test, shot): gra zatrzymana w oknie zawiesza się, dopóki jej nie wznowisz.

Debugowanie z AI

AI lepiej debuguje z debuggerem niż z var_dump(): czyta prawdziwe wartości, jedno pytanie naraz, i niczego nie zmienia w twoim kodzie. Dostępne są dwa serwery MCP. Używaj jednego naraz (oba nasłuchują na porcie 9003).

1. Serwer JumPHP: bin/jumphp debug

Własny debugger IDE jako serwer MCP (działa w Dockerze, z Xdebug):

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

Jego narzędzia:

Narzędzie Co robi
debug_breakpoints ustawia punkty przerwania pliku (lines lub {line, condition}), bez ścieżki wypisuje je, clear_all
debug_exceptions wyjątki zatrzymujące program (* = wszystkie, [] = żadne)
debug_wait czeka, aż program zatrzyma się na punkcie przerwania lub wyjątku, po czym podaje miejsce, stos i zmienne
debug_state gdzie się zatrzymał, stos, zmienne ramki
debug_step step_over, step_into, step_out, run, stop: czeka na następne zatrzymanie
debug_run_to uruchamia do wskazanej linii
debug_eval oblicza wyrażenie PHP w miejscu zatrzymania
debug_variables zmienne ramki lub elementy potomne jednej z nich ($this->player, $list[3])
debug_set_value nadaje zmiennej nową wartość (wyrażenie PHP)

Ścieżki są względne wobec projektu. Claude uruchamia program sam, w tle, z JUMPHP_XDEBUG=9003, a następnie wywołuje debug_wait.

2. Serwer PHP Debuggera: dbgp mcp

PHP Debugger dostarcza własny serwer MCP w małym programie dbgp (licencja MIT; Linux i macOS, amd64 i arm64; Windows amd64).

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

# for this project / for all your projects
claude mcp add dbgp -- dbgp mcp
claude mcp add --scope user dbgp -- dbgp mcp

W Claude Code /mcp pokazuje, że jest połączony. Jego narzędzia, pod nazwami z dokumentacji PHP Debuggera:

  • połączenie: status, listen, unlisten, sessions, wait_for_session, detach;
  • punkty przerwania: add_breakpoint, remove_breakpoint, breakpoints;
  • uruchamianie: continue, wait_for_stop, stop;
  • oglądanie: stack, variables, variable, variable_value, source, output, warnings;
  • działanie: eval, set_variable;
  • Docker / zdalnie: add_path_mapping, path_mappings.

Przydatne flagi (dbgp mcp -h pokazuje wszystkie): -php-port PORT (port, z którym łączy się PHP, domyślnie 9003), -mcp-port PORT, -idekey KEY, -map LOCAL=REMOTE (mapowanie ścieżek, można powtarzać) oraz -no-eval, które zabrania eval, set_variable i warunkowych punktów przerwania: AI może wtedy tylko patrzeć. Nie ukrywa ono wartości, więc hasła i klucze pozostają dla niego widoczne.

Przez bin/jumphp polecenie JUMPHP_DEBUGGER=php-debugger bin/jumphp debug uruchamia dbgp mcp za ciebie (wymaga zainstalowanego dbgp na twoim komputerze). Następnie uruchom program z tym samym silnikiem:

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

Przykładowa sesja

Ty, do Claude Code:

Wynik w grze pong rośnie o 2 zamiast o 1, gdy piłka mija lewą paletkę. Użyj debuggera, nie var_dump. Ustaw punkt przerwania tam, gdzie wynik jest zwiększany (zajrzyj do PlayScene), uruchom bin/jumphp test pong z JUMPHP_XDEBUG=9003, zatrzymaj się na nim, odczytaj zmienne i powiedz mi dlaczego. Napraw dopiero po tym, jak pokażesz mi przyczynę.

Co AI wtedy robi, za pomocą powyższych narzędzi:

  1. znajduje linię dodającą punkt i ustawia tam punkt przerwania, z warunkiem, jeśli linia wykonuje się w każdej klatce ($this->ballX < 0);
  2. uruchamia test w tle i czeka na zatrzymanie (debug_wait / wait_for_stop);
  3. odczytuje $this->score, $this->scored i stos, by zobaczyć, kto wywołał tę linię;
  4. raz wychodzi z funkcji (debug_step step_out), by zobaczyć drugiego wywołującego: punkt jest liczony dwa razy;
  5. sprawdza swój pomysł, niczego nie edytując: nadaje $this->scored wartość (debug_set_value / set_variable) i kontynuuje, by zobaczyć, że wynik pozostaje poprawny;
  6. dopiero wtedy edytuje kod i ponownie uruchamia test, bez punktu przerwania.

Wskazówki

  • Powiedz to wprost: „użyj debuggera". Inaczej agent często wraca do var_dump().
  • Podaj polecenie pokazujące błąd, czego oczekujesz i gdzie go podejrzewasz.
  • Małe kroki: kilka step_over, potem oglądanie. Warunkowy punkt przerwania ($enemy->hp <= 0) jest lepszy niż przechodzenie przez 600 klatek.
  • Pozwól mu czytać zmienne i obliczać wyrażenia: żadnych var_dump(), żadnych echo, nic do sprzątania.
  • Wybieraj uruchomienia headless (test, shot, php) zamiast okna.
  • Sekrety: AI widzi każdą zmienną, którą czyta (hasła, tokeny, klucze API). Debuguj na danych testowych i użyj -no-eval z dbgp, jeśli nie chcesz, by wykonywało kod w twoim programie.
  • Nie zostawiaj serwera MCP debuggera podłączonego w projekcie, w którym nie debugujesz: usuń go poleceniem claude mcp remove.

Rozwiązywanie problemów

Nic się nie zatrzymuje / „did not connect". Czy jakiś debugger nasłuchuje na tym porcie (okno Debug w IDE albo serwer MCP)? Program musi być uruchomiony z JUMPHP_XDEBUG=<port> i tym samym silnikiem co nasłuchujący.

Port jest już zajęty. Dwa nasłuchujące na 9003: IDE i bin/jumphp debug (albo dbgp mcp), albo dwa IDE. Zatrzymaj jedno lub użyj innego portu: JUMPHP_DEBUG_PORT=9010 bin/jumphp debug z JUMPHP_XDEBUG=9010, albo dbgp -php-port 9010 mcp.

Punkt przerwania nigdy nie jest osiągany. Jest na linii bez kodu (komentarz, pusta linia, zamykający nawias klamrowy) lub w pliku, którego program nigdy nie ładuje. Wywołaj debug_state / spójrz na stos, by zobaczyć, gdzie jest. Przy -map lub w IDE: ścieżki muszą się zgadzać (patrz niżej).

Ścieżki w Dockerze. bin/jumphp montuje twój projekt w /workspace w kontenerze: debugger podaje file:///workspace/.... IDE i bin/jumphp debug same mapują to na pliki projektu, a podawane ścieżki są względne wobec projektu. Samo dbgp mcp wymaga mapowania katalogów: dbgp mcp -map /home/you/project=/workspace.

PHP 8.6 (runtime async). PHP Debugger tam nie działa: używany jest Xdebug. Aby użyć PHP Debuggera, debuguj na domyślnym runtime (PHP 8.5) albo na czas sesji usuń runtime: async.

Gry w przeglądarce. Debugger działa na runtime desktopowym. W przeglądarce odtwórz błąd za pomocą bin/jumphp test lub shot na desktopie.

Zobacz też Programowanie, uruchamianie i testy, Claude w IDE oraz IDE Remote.