RU

Отладка с Xdebug или PHP Debugger, вручную или с ИИ

В JumPHP IDE есть настоящий пошаговый отладчик: вы останавливаете программу на строке, смотрите переменные, меняете одну из них и идёте дальше шаг за шагом. Он говорит на DBGp, протоколе Xdebug, поэтому может управлять двумя движками:

  • Xdebug, классический (по умолчанию);
  • PHP Debugger, более новый отладчик DBGp, бесплатный и с открытым кодом, совместимый с настройками Xdebug, с почти нулевыми накладными расходами.

В IDE оба работают одинаково. Отладчик можно также передать ИИ (Claude Code): он сам ставит точки останова, запускает программу, читает переменные и находит ошибку.

Какой движок выбрать

Xdebug PHP Debugger
В JumPHP по умолчанию, все рантаймы десктопный рантайм (PHP 8.2–8.5)
Накладные расходы PHP заметно медленнее «near-zero overhead when idle», всегда включён, без триггера
Async-рантайм (PHP 8.6, runtime: async) да нет: используется Xdebug, и IDE сообщает об этом
ИИ MCP-сервер JumPHP (bin/jumphp debug) собственный MCP-сервер (dbgp mcp), который видит и вывод скрипта, и предупреждения PHP

На практике: выбирайте PHP Debugger для повседневной отладки, для долгих запусков (игра на 600 кадров, набор тестов) и для отладки с ИИ. Оставайтесь на Xdebug, если работаете с async-рантаймом (потоки) или вам нужно то, что умеет только Xdebug. В IDE они взаимозаменяемы, так что можно попробовать оба на одном проекте.

На странице PHP Debugger нет никаких цифр бенчмарков: там лишь сказано, что стоимость почти нулевая, пока вы не отлаживаете. Если разница важна, измерьте её на своём проекте.

Выбор движка в IDE

  • Кнопка Отладка в шапке (жук рядом с «Запуск», Shift+F9) раскрывает меню: Отладка с помощью (Xdebug или PHP Debugger, для этого запуска) и Движок по умолчанию (движок, который используется при обычном щелчке). Щелчок правой кнопкой по кнопке открывает то же меню.
  • Первый запуск с данным движком собирает образ Docker (около минуты). Последующие стартуют сразу.
  • Уведомление сообщает, что программа так и не подключилась к отладчику (завершилась раньше или за 3 минуты ничего не произошло). Причина обычно видна в выводе окна «Запуск».

Выбор движка из терминала

Всё идёт через bin/jumphp, как всегда:

# 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> включает пошаговую отладку: PHP подключается к отладчику, слушающему этот порт вашего компьютера (composer, phpstan и php -l работают без неё).
  • JUMPHP_DEBUGGER=xdebug|php-debugger выбирает движок (по умолчанию xdebug).
  • С php-debugger bin/jumphp один раз собирает образ docker/desktop-phpdebugger на основе десктопного образа, который остаётся без него.
  • На async-рантайме (PHP 8.6) выводится сообщение «PHP Debugger does not run on PHP 8.6 (async runtime): Xdebug is used», и работает Xdebug.

Отладка вручную в IDE

  1. Точка останова: щёлкните в полях слева от строки PHP. Правый щелчок задаёт условие (выражение PHP: остановка только когда оно истинно, например $this->score < 0); Ctrl+F8 ставит точку на позиции курсора. Точки останова хранятся для проекта и следуют за своими строками при редактировании.
  2. Отладка (Shift+F9): программа запускается и останавливается на первой точке останова. Строка подсвечивается, открывается окно инструментов Debug.
  3. Смотрите: стек вызовов (щёлкните кадр, чтобы увидеть его переменные), переменные в виде дерева, читаемого по требованию, watches и поле для вычисления любого выражения PHP в месте остановки.
  4. Изменение значения: двойной щелчок по переменной или F2, введите выражение PHP (9, "Ada", [1, 2], null) и продолжайте с новым значением.
  5. Перемещение: Продолжить F9, Шаг с обходом F8, Шаг с заходом F7, Шаг с выходом Shift+F8, Выполнить до курсора Alt+F9, Остановить.
  6. Исключения: Останавливаться на исключениях… (значок предупреждения окна Debug): * или имена классов (TypeError, App\GameOver). Остановка происходит там, где исключение выброшено, перехвачено оно или нет, с показом самого исключения и его сообщения.

Инспектор при наведении (в следующем обновлении IDE): когда программа остановлена на точке останова, наведите мышь на переменную в редакторе, чтобы получить раскрываемое дерево её значения с кнопками Copy и Edit.

Совет для игр: отлаживайте headless-запуски (test, shot): игра, остановленная внутри окна, зависает, пока вы её не продолжите.

Отладка с ИИ

ИИ отлаживает лучше с отладчиком, чем с var_dump(): он читает реальные значения, по одному вопросу за раз, и ничего не меняет в вашем коде. Доступны два MCP-сервера. Используйте один за раз (оба слушают порт 9003).

1. Сервер JumPHP: bin/jumphp debug

Собственный отладчик IDE как MCP-сервер (работает в Docker, с Xdebug):

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

Его инструменты:

Инструмент Что делает
debug_breakpoints ставит точки останова файла (lines или {line, condition}), без пути перечисляет их, clear_all
debug_exceptions исключения, останавливающие программу (* = все, [] = никаких)
debug_wait ждёт, пока программа остановится на точке останова или исключении, затем выдаёт место, стек и переменные
debug_state где остановлена, стек, переменные кадра
debug_step step_over, step_into, step_out, run, stop: ждёт следующей остановки
debug_run_to выполняет до строки
debug_eval вычисляет выражение PHP в месте остановки
debug_variables переменные кадра или дочерние элементы одной из них ($this->player, $list[3])
debug_set_value задаёт переменной новое значение (выражение PHP)

Пути указываются относительно проекта. Claude запускает программу сам, в фоне, с JUMPHP_XDEBUG=9003, затем вызывает debug_wait.

2. Сервер PHP Debugger: dbgp mcp

PHP Debugger поставляет собственный MCP-сервер в небольшой программе dbgp (лицензия MIT; Linux и macOS, amd64 и 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

В Claude Code команда /mcp показывает, что он подключён. Его инструменты под именами из документации PHP Debugger:

  • соединение: status, listen, unlisten, sessions, wait_for_session, detach;
  • точки останова: add_breakpoint, remove_breakpoint, breakpoints;
  • выполнение: continue, wait_for_stop, stop;
  • просмотр: stack, variables, variable, variable_value, source, output, warnings;
  • действия: eval, set_variable;
  • Docker / удалённо: add_path_mapping, path_mappings.

Полезные флаги (dbgp mcp -h показывает все): -php-port PORT (порт, к которому подключается PHP, по умолчанию 9003), -mcp-port PORT, -idekey KEY, -map LOCAL=REMOTE (сопоставление путей, можно повторять) и -no-eval, запрещающий eval, set_variable и условные точки останова: ИИ может только смотреть. Он не скрывает значения, поэтому пароли и ключи остаются ему видны.

Через bin/jumphp команда JUMPHP_DEBUGGER=php-debugger bin/jumphp debug сама запускает dbgp mcp (на вашем компьютере должен быть установлен dbgp). Затем запустите программу с тем же движком:

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

Пример сеанса

Вы, Claude Code:

Счёт в игре pong растёт на 2 вместо 1, когда мяч пролетает мимо левой ракетки. Используй отладчик, а не var_dump. Поставь точку останова там, где увеличивается счёт (смотри в PlayScene), запусти bin/jumphp test pong с JUMPHP_XDEBUG=9003, остановись на ней, прочитай переменные и скажи мне, почему так. Исправляй только после того, как покажешь причину.

Что ИИ делает дальше с помощью инструментов выше:

  1. находит строку, добавляющую очко, и ставит там точку останова, с условием, если строка выполняется на каждом кадре ($this->ballX < 0);
  2. запускает тест в фоне и ждёт остановки (debug_wait / wait_for_stop);
  3. читает $this->score, $this->scored и стек, чтобы увидеть, кто вызвал эту строку;
  4. один раз выходит из функции (debug_step step_out), чтобы увидеть второго вызывающего: очко засчитывается дважды;
  5. проверяет свою идею, ничего не правя: присваивает $this->scored значение (debug_set_value / set_variable) и продолжает, чтобы убедиться, что счёт остаётся верным;
  6. и только потом правит код и снова запускает тест, без точки останова.

Советы

  • Скажите прямо: «используй отладчик». Иначе агент часто возвращается к var_dump().
  • Дайте ему команду, показывающую ошибку, то, чего вы ждёте, и место, где подозреваете причину.
  • Маленькие шаги: несколько step_over, затем просмотр. Условная точка останова ($enemy->hp <= 0) лучше, чем прохождение 600 кадров.
  • Пусть он читает переменные и вычисляет выражения: никаких var_dump(), никаких echo, нечего убирать после.
  • Предпочитайте headless-запуски (test, shot, php) окну.
  • Секреты: ИИ видит каждую прочитанную переменную (пароли, токены, ключи API). Отлаживайте на тестовых данных и используйте -no-eval с dbgp, если не хотите, чтобы он выполнял код в вашей программе.
  • Не оставляйте MCP-сервер отладчика подключённым в проекте, где вы не отлаживаете: удалите его командой claude mcp remove.

Устранение неполадок

Ничего не останавливается / «did not connect». Слушает ли порт какой-нибудь отладчик (окно Debug в IDE или MCP-сервер)? Программа должна быть запущена с JUMPHP_XDEBUG=<port> и тем же движком, что и слушающий.

Порт уже занят. Два слушателя на 9003: IDE и bin/jumphp debug (или dbgp mcp), либо две IDE. Остановите один или возьмите другой порт: JUMPHP_DEBUG_PORT=9010 bin/jumphp debug с JUMPHP_XDEBUG=9010, или dbgp -php-port 9010 mcp.

Точка останова никогда не срабатывает. Она стоит на строке без кода (комментарий, пустая строка, закрывающая скобка) или в файле, который программа никогда не загружает. Вызовите debug_state / посмотрите стек, чтобы увидеть, где программа. С -map или в IDE пути должны совпадать (ниже).

Пути в Docker. bin/jumphp монтирует ваш проект в /workspace в контейнере: отладчик сообщает file:///workspace/.... IDE и bin/jumphp debug сами сопоставляют это с файлами проекта, а указываемые вами пути относительны проекта. С одним dbgp mcp сопоставьте папки: dbgp mcp -map /home/you/project=/workspace.

PHP 8.6 (async-рантайм). PHP Debugger там не работает: используется Xdebug. Чтобы пользоваться PHP Debugger, отлаживайте на рантайме по умолчанию (PHP 8.5) или уберите runtime: async на время сеанса.

Браузерные игры. Отладчик работает на десктопном рантайме. В браузере воспроизведите ошибку через bin/jumphp test или shot на десктопе.

См. также Писать код, запускать и тестировать, Claude в IDE и IDE Remote.