Configuring Xdebug
Xdebug lets an IDE stop PHP code on breakpoints while the application handles a web request, console command, or test. The IDE listens for debug connections. PHP starts the request and Xdebug connects back to the IDE.
Yii works with the regular Xdebug setup. Configure Xdebug for the PHP runtime that executes the code and make sure the IDE can map runtime paths to project files.
Check Xdebug
Use Xdebug 3. The default debug port is 9003.
Without Docker, install Xdebug for the PHP executable that runs the application, then check it:
php --version
php --ri xdebugIn php.ini or an Xdebug-specific ini file, enable step debugging:
xdebug.mode=develop,debug
xdebug.start_with_request=trigger
xdebug.client_host=127.0.0.1
xdebug.client_port=9003trigger starts a debug session only when a browser extension, query parameter, cookie, or XDEBUG_SESSION environment variable asks for it.
With Docker, the Yii application template installs Xdebug in the development image. Enable step debugging in docker/dev/override.env:
XDEBUG_MODE=develop,debug
XDEBUG_CONFIG="client_host=host.docker.internal idekey=phpstorm"Keep the default SERVER_NAME=:80 from docker/dev/.env unless the application needs a different Caddy address. Set the browser port with DEV_PORT in docker/.env:
DEV_PORT=80On Linux, Docker must resolve host.docker.internal to the host gateway. The current Yii application template already has this in docker/compose.yml:
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"Rebuild the development image if Xdebug was added after the image had already been built:
make buildPhpStorm
In Settings > PHP > Debug, check that Xdebug listens on port 9003. Start listening with Run > Start Listening for PHP Debug Connections.
For browser debugging, install a browser extension from Settings > PHP > Debug. In the extension options, use phpstorm as the IDE key.
When PHP runs in Docker, configure a server in Settings > PHP > Servers:
- Name:
localhost. - Host:
localhost. - Port:
80, or the host port configured byDEV_PORT. - Debugger:
Xdebug. - Path mapping: map the project root on the host to
/appin the container.
Use the project root for the mapping. Mapping only public/ leaves files under src/, config/, and vendor/ unmapped. The path in the container must match the path used by PHP. In the default template, the project is mounted into /app.
For local PHP, PhpStorm usually uses the same filesystem paths as PHP, so path mappings are usually unnecessary.
VS Code
Install the PHP Debug extension.
For PHP that runs on the same filesystem as VS Code, create .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003
}
]
}For Docker, add path mappings:
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/app": "${workspaceFolder}"
}
}
]
}Start this configuration before running the web request, command, or test.
Zed
Install or enable the PHP extension in Zed. It provides the Xdebug debug adapter.
Create .zed/debug.json:
[
{
"label": "PHP: Listen to Xdebug",
"adapter": "Xdebug",
"request": "launch",
"port": 9003
}
]For Docker, add path mappings:
[
{
"label": "PHP: Listen to Xdebug",
"adapter": "Xdebug",
"request": "launch",
"port": 9003,
"pathMappings": {
"/app": "$ZED_WORKTREE_ROOT"
}
}
]Start the configuration with debugger: start before running the web request, command, or test. Zed can also load debug configurations from .vscode/launch.json when .zed/debug.json is absent.
Debug a web request
Without Docker:
Start listening in the IDE.
Put a breakpoint in an action or middleware.
Start the built-in server with an Xdebug trigger:
shell./yii serve --xdebugOpen or reload the page in the browser.
The --xdebug option passes XDEBUG_MODE=debug XDEBUG_TRIGGER=yes to the built-in PHP server. If you use another web server, enable debugging with the browser extension and reload the page.
With Docker:
Add the Docker Xdebug variables to
docker/dev/override.env.Start or restart the development containers:
shellmake upStart listening in the IDE.
Put a breakpoint in an action or middleware.
Enable debugging in the browser extension and reload the page.
If the IDE accepts a connection and the breakpoint stays inactive, check path mappings first.
Debug a console command
Without Docker, start the command with an Xdebug trigger:
XDEBUG_MODE=debug XDEBUG_SESSION=phpstorm ./yii helloWith Docker, pass the trigger to the container:
docker compose -f docker/compose.yml -f docker/dev/compose.yml run --rm \
-e XDEBUG_MODE=debug \
-e XDEBUG_SESSION=phpstorm \
-e PHP_IDE_CONFIG=serverName=localhost \
app ./yii helloUse the command name and arguments you need instead of hello.
Debug tests
Without Docker, start the test runner with an Xdebug trigger:
XDEBUG_MODE=debug XDEBUG_SESSION=phpstorm vendor/bin/codecept runWith Docker, configure docker/test/override.env:
XDEBUG_MODE=debug,coverage
XDEBUG_CONFIG="client_host=host.docker.internal idekey=phpstorm"Then run the test container with a trigger:
docker compose -f docker/compose.yml -f docker/test/compose.yml run --rm \
-e XDEBUG_SESSION=phpstorm \
-e PHP_IDE_CONFIG=serverName=localhost \
app ./vendor/bin/codecept runUse make test for regular test runs. Use the explicit docker compose command when you need to pass debug-only environment variables to one run.
Troubleshooting
- The IDE must listen before PHP starts the request.
- Xdebug connects from PHP to the IDE. Allow incoming connections to port
9003in the host firewall. - In Docker,
client_hostmust be reachable from the container. The Yii template useshost.docker.internal. - For CLI and tests, set
XDEBUG_SESSION=phpstormor another trigger accepted by your Xdebug configuration. - For Docker path mappings, map the host project root to
/app. - To inspect connection attempts, temporarily add
log=/app/runtime/xdebug.logtoXDEBUG_CONFIG.