Перейти к содержанию

PHP DBGp

Язык: PHP · Транспорт: stdio

php-dbgp-adapter — собственный адаптер Bugsaur, собираемый из того же workspace. Он заменяет привычный мост DAP↔DBGp и не зависит ни от Node.js, ни от npm, ни от VS Code, ни от vscode-php-debug. Во время работы участвуют только bugsaur, php-dbgp-adapter и Xdebug.

Запись каталога:

[adapters.php]
id = "php"
command = "php-dbgp-adapter"
transport = "stdio"

[adapters.php.launch_arguments]
port = 9003
sessionMode = "server"

Обратите внимание: это единственная встроенная запись с умолчаниями в launch_arguments — PHP-профиль, не назвавший ни port, ни sessionMode, получит 9003 и server.

Установка

Внешнего ничего. make build собирает адаптер рядом с bugsaur:

make build
export PATH="$PWD/target/debug:$PATH"
command -v php-dbgp-adapter

Почему PHP устроен принципиально иначе

Xdebug работает по DBGp, а не по DAP, и делает это наоборот по сравнению с адаптерами других языков: Xdebug подключается к отладчику, а не отладчик запускает программу.

Поэтому php-dbgp-adapter открывает порт и ждёт. Тот, кто запускает PHP — PHP-FPM, Docker, вызов из CLI, — находится вне управления Bugsaur.

Два следствия:

  • cwd, env и args не применяются: передавать их некому;
  • из тела DAP читаются только три ключа — port, pathMappings, sessionMode — плюс testCommand для отладки теста под курсором.

Три ключа

port

DBGp-порт, который слушает адаптер; по умолчанию 9003. Он обязан совпадать с xdebug.client_port в PHP-среде.

Порт на машине один: двум проектам, отлаживающимся одновременно, нужны разные порты.

sessionMode

Значение Смысл
server PHP уже работает (FPM, встроенный сервер, web-контейнер); адаптер ждёт запросов
cli одноразовый скрипт; адаптер обязан слушать до его старта

pathMappings

Путь контейнера в путь хоста:

pathMappings = { "/app" = "${root}" }

Нужен всякий раз, когда PHP работает там, где пути другие, — то есть практически при любой схеме с Docker. Без него точки останова не привязываются, а остановки происходят без исходника. См. Отображения путей.

testCommand

Для отладки PHPUnit-теста под курсором профиль передаёт команду, запускающую PHPUnit там, где живёт PHP:

[profiles.docker.launch_arguments]
testCommand = ["docker", "compose", "exec", "-T", "-e", "XDEBUG_TRIGGER=1", "php", "php", "vendor/bin/phpunit"]

Она выполняется после того, как адаптер начал слушать, поэтому к моменту обратного соединения Xdebug listener уже готов. Переменная XDEBUG_TRIGGER=1 также передаётся внешнему процессу.

Обязательные настройки Xdebug

xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003

client_host — это host.docker.internal из контейнера и localhost, когда PHP работает на той же машине.

Диагностика

Симптом Причина Что делать
php-dbgp-adapter не найден каталог сборки не в PATH выведите его, см. выше
Никто не подключается запрос ушёл до старта listener'а повторите запрос после запуска сессии
Не подключается вообще никогда xdebug.mode не debug или выключен start_with_request почините ini и перезапустите PHP
Порт занят его держит другой проект дайте каждому проекту свой порт
Останавливается без исходника pathMappings отсутствует или неверен Исходник не найден
До первого запроса точки останова pending спросить пока некого это нормально — отправьте запрос