PHP DBGp¶
Language: PHP · Transport: stdio
php-dbgp-adapter is Bugsaur's own adapter, built from the same workspace. It
replaces the usual DAP↔DBGp bridge and depends on no Node.js, npm, VS Code or
vscode-php-debug. At runtime only bugsaur, php-dbgp-adapter and Xdebug are
involved.
The catalog entry:
[adapters.php]
id = "php"
command = "php-dbgp-adapter"
transport = "stdio"
[adapters.php.launch_arguments]
port = 9003
sessionMode = "server"
Note that this is the one built-in entry with default launch_arguments: a PHP
profile that names neither port nor sessionMode gets 9003 and server.
Install¶
Nothing external. make build produces the adapter next to bugsaur:
Why PHP is structurally different¶
Xdebug uses DBGp, not DAP, and it works the other way round from the adapters of other languages: Xdebug connects to the debugger, rather than the debugger launching the program.
So php-dbgp-adapter opens a port and waits. Whoever starts PHP — PHP-FPM,
Docker, a CLI invocation — is outside Bugsaur's control.
Two consequences:
cwd,envandargsdo not apply. There is no process to give them to.- Only three keys are read from the DAP body:
port,pathMappings,sessionMode— plustestCommandfor the test-under-cursor flow.
The three keys¶
port¶
The DBGp port the adapter listens on; 9003 by default. It must match
xdebug.client_port in the PHP environment.
One port per machine: two projects debugging at once need different ports.
sessionMode¶
| Value | Meaning |
|---|---|
server |
PHP is already running (FPM, built-in server, web container); the adapter waits for requests |
cli |
a one-shot script; the adapter must be listening before it starts |
pathMappings¶
Container path to host path:
Required whenever PHP runs somewhere with different paths — which in practice means any Docker setup. Without it, breakpoints never bind and stops show no source. See Path mappings.
testCommand¶
For debugging a PHPUnit test under the cursor, the profile supplies the command that runs PHPUnit where PHP lives:
[profiles.docker.launch_arguments]
testCommand = ["docker", "compose", "exec", "-T", "-e", "XDEBUG_TRIGGER=1", "php", "php", "vendor/bin/phpunit"]
It runs after the adapter has started listening, so the listener is up before
Xdebug connects back. XDEBUG_TRIGGER=1 is also passed to the external process.
Required Xdebug settings¶
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
client_host is host.docker.internal from a container and localhost when PHP
runs on the same machine.
Diagnostics¶
| Symptom | Cause | Fix |
|---|---|---|
php-dbgp-adapter not found |
the build directory is not on PATH |
export it, above |
| Nothing ever connects | the request ran before the listener was up | repeat the request after starting the session |
| Nothing ever connects, ever | xdebug.mode is not debug, or start_with_request is off |
fix the ini and restart PHP |
| Port already in use | another project holds it | give each project its own port |
| Stops without source | pathMappings missing or wrong |
Source not found |
| Breakpoints stay pending before the first request | nobody to ask yet | normal — send a request |