
September 08, 2026
12 min read
By Kokil Thapa | Last reviewed: September 2026
PHP Xdebug 3 configuration for modern IDEs changed sharply from Xdebug 2. You no longer scatter a dozen mystery directives across three ini files and hope PhpStorm connects. Xdebug 3 uses a single mode switch, defaults to port 9003, and expects your IDE to initiate the debug session. That sounds simpler until Docker, WSL2, or a mismatched PHP binary on Ubuntu breaks the handshake. This guide walks through a working setup for VS Code, PhpStorm, and containerised Laravel apps on PHP 8.3 through 8.5.
xdebug.mode=debug, xdebug.start_with_request=trigger, xdebug.client_host=127.0.0.1 (or your Docker host IP), and port 9003. Install the IDE extension, set the same port and path mappings, then trigger with a cookie or browser extension.I've spent too many afternoons on Ubuntu PHP server setups where the app ran fine but breakpoints never fired. The fix is almost always ini placement, not the IDE. Start with one verified PHP binary, one ini file, and one listening IDE port before you touch framework code.
How Do You Configure PHP Xdebug 3 for Modern IDEs?
Xdebug 3 splits concerns into modes. You pick what you need instead of loading every feature at once. For daily IDE work, debug is the only mode you require. Add develop if you want improved var_dump() output via xdebug.mode=debug,develop.
Official reference: the Xdebug step debugger documentation lists every directive. Treat that page as the source of truth when a release adds new settings.
Install Xdebug on Ubuntu with the correct PHP version
Match the Xdebug build to the exact PHP binary your web server uses. A common mistake is installing for CLI while Apache or PHP-FPM loads a different version. On Ubuntu 22.04 or 24.04 with PHP 8.4:
sudo apt install php8.4-xdebug
php8.4 -v
php8.4 -m | grep -i xdebug Prefer PECL when you need a specific Xdebug patch level across multiple PHP versions side by side:
sudo pecl install xdebug
php8.4 -i | grep "Loaded Configuration File"
php8.4 -i | grep "Scan this dir" Place overrides in a dedicated drop-in such as /etc/php/8.4/mods-available/xdebug.ini rather than editing the main php.ini. That keeps upgrades clean and mirrors how I configure production servers alongside OPcache tuning for production.
Minimal ini block that works in 2026
Copy this baseline into your Xdebug ini file. Adjust the client host section for your environment.
zend_extension=xdebug.so
xdebug.mode=debug
xdebug.start_with_request=trigger
xdebug.client_host=127.0.0.1
xdebug.client_port=9003
xdebug.idekey=VSCODE
xdebug.log=/tmp/xdebug.log
xdebug.log_level=7 Reload the SAPI you actually debug through — not only CLI:
sudo systemctl reload php8.4-fpm
sudo systemctl reload apache2 Confirm the loaded values:
php8.4 -i | grep xdebug.mode
php8.4 -i | grep xdebug.client What PHP Xdebug 3 Configuration Do Modern IDEs Like VS Code Need?
Visual Studio Code remains the most common free IDE in PHP teams. Install the PHP Debug extension by Xdebug (publisher: xdebug). Create .vscode/launch.json at your project root:
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/html": "${workspaceFolder}"
},
"xdebugSettings": {
"max_data": 65535,
"show_local_vars": 1
}
}
]
} Path mappings are non-negotiable in Docker or Vagrant. The left side must match the absolute path inside the container. The right side is your local checkout. One character wrong and breakpoints show as unverified grey dots.
Trigger debugging without leaving Xdebug always on
Never run xdebug.start_with_request=yes on shared staging servers. It adds overhead and opens debug sessions you did not intend. Use trigger mode and activate per request:
- Browser extension: Xdebug Helper for Chrome or Firefox — set IDE key to
VSCODEorPHPSTORM. - Query string: append
?XDEBUG_SESSION_START=VSCODEto any URL. - Cookie: set
XDEBUG_SESSION=VSCODEfor the session duration. - CLI:
XDEBUG_SESSION=1 php artisan migratefor one-off Artisan debugging.
For Laravel queue workers, pass the env var in your supervisor unit or use php artisan queue:listen from a terminal where you have already exported it. Background workers do not read browser cookies.
PhpStorm-specific PHP Xdebug 3 settings
PhpStorm still dominates agency workflows. Open Settings → PHP → Debug. Set Xdebug port to 9003 — not 9000. Enable Can accept external connections. Under PHP → Servers, add your vhost with path mappings identical to VS Code.
PhpStorm listens automatically when you click the phone icon. Match xdebug.idekey in ini to the IDE key field if you use multiple developers on one machine. On a Laravel Livewire booking project I maintain, path mapping between Homestead and macOS was the only blocker after a PHP 8.4 upgrade.
Which PHP Xdebug 3 IDE Settings Fix Docker and WSL2 Connection Problems?
Containerised apps introduce a network hop. Inside the container, 127.0.0.1 points to the container itself — not your laptop. That single fact causes most "Xdebug never connects" tickets.
Docker Compose configuration
Add environment variables or ini overrides so Xdebug reaches the host:
services:
app:
environment:
XDEBUG_MODE: debug
XDEBUG_CONFIG: "client_host=host.docker.internal client_port=9003 start_with_request=trigger"
extra_hosts:
- "host.docker.internal:host-gateway" On Linux without Docker Desktop, replace host.docker.internal with your bridge IP — often discoverable via ip addr show docker0. Some teams hard-code 172.17.0.1 but verify rather than assume.
WSL2 on Windows
When PHP runs inside WSL2 and VS Code runs on Windows, set xdebug.client_host to the Windows host IP from /etc/resolv.conf (the nameserver line). That IP changes after sleep or VPN connect. A small shell alias to refresh it saves repeated frustration.
Enable xdebug.log temporarily when connections fail. Tail it during a request:
tail -f /tmp/xdebug.log Look for "Connection refused" or "Time-out". Cross-check against PHP-FPM pool settings if requests never reach PHP at all. Firewalls on port 9003 are rare locally but common on remote dev VMs managed through Linux server administration contracts.
How Does PHP Xdebug 3 Configuration Differ From Xdebug 2 in Modern IDEs?
If you learned debugging on Xdebug 2, your muscle memory will betray you. Several directives were renamed or removed. IDEs expect the new defaults.
| Setting | Xdebug 2 | Xdebug 3 | Notes for IDEs |
|---|---|---|---|
| Enable debug | xdebug.remote_enable=1 | xdebug.mode=debug | Modes are comma-separated flags |
| IDE port | 9000 default | 9003 default | Update every launch.json and firewall rule |
| Host directive | xdebug.remote_host | xdebug.client_host | Same purpose, new name |
| Autostart | xdebug.remote_autostart | xdebug.start_with_request | Use trigger in shared envs |
| IDE key | xdebug.idekey | xdebug.idekey | Unchanged — match browser extension |
| Profiler | xdebug.profiler_enable | xdebug.mode=profile | Separate mode — do not mix with debug daily |
The port change alone breaks more setups than any other single line. Search your repo for 9000 in docker-compose, nginx configs, and old wiki pages. Replace with 9003 everywhere.
Profiler and trace modes now sit behind the same mode switch. For performance work, spin up xdebug.mode=profile briefly rather than leaving debug on production-like staging. Pair profiling sessions with PHP memory limit analysis when you chase slow endpoints.
What PHP Xdebug 3 Configuration Checklist Works for Laravel and Symfony Projects?
Framework projects add layers — front controllers, public/ docroots, and env-based config. The Xdebug ini still lives at the PHP layer, but your IDE must map into public/index.php entry paths correctly.
Laravel 12 or 13 on PHP 8.3+
- Install Xdebug for the PHP-FPM version serving the site — verify with
php-fpm8.4 -iif needed. - Set trigger mode; avoid autostart on shared Homestead or Sail instances.
- Map container
/var/www/htmlto your local clone in launch.json. - Place breakpoints in route closures, controllers, or jobs — not in compiled Blade views.
- Run
php artisan config:clearonly when debugging config cache issues; Xdebug itself does not need it.
Laravel Sail ships a optional Xdebug install path. If you use Sail, follow its documented SAIL_XDEBUG_MODE variables rather than hand-editing container ini. For custom stacks, mirror patterns from modern Laravel architecture and keep dev tooling out of production deploy artefacts.
Symfony 8.1 and multi-env setups
Symfony CLI can proxy requests and inject its own PHP binary. Confirm which binary serves symfony server:start with symfony php -i | grep xdebug. Symfony 8.1 requires PHP 8.4.1 minimum — align Xdebug with that exact build.
PHPUnit and Pest tests also respect Xdebug when triggered. In CI pipelines, disable Xdebug entirely for speed. Use PHPStan static analysis and Pint or CS Fixer for automated checks that do not need a debugger attached.
When to skip Xdebug entirely
Not every problem deserves a breakpoint. Log channels, Laravel Telescope, or Symfony Profiler cover many production-like issues faster. Reach for Xdebug when state mutates across middleware, payment callbacks fail silently, or queue serialization behaves oddly — cases I've hit on Laravel eCommerce platforms.
How Do You Keep PHP Xdebug 3 Off Production While Debugging Locally?
Xdebug must not load on production web nodes. It adds measurable latency and exposes internal structure. Separate ini files per environment or use conditionally loaded modules.
# Production — disable entirely
# /etc/php/8.4/fpm/conf.d/99-xdebug-prod.ini
; zend_extension=xdebug.so commented out or package removed
# Local dev only
xdebug.mode=debug
xdebug.start_with_request=trigger On Deployer 7 pipelines I maintain for legal-tech sister sites, Xdebug is absent from production releases entirely. Dev VMs get the package through Ansible provisioning playbooks. Composer 2.10 dev dependencies like PHPUnit may suggest Xdebug for coverage — run coverage on CI agents, not live traffic servers.
If you need remote debugging against a staging server — rare and risky — restrict by IP, use trigger mode, and disable afterward. For most teams, reproduce locally with synced database snapshots. Tools like the JSON formatter help inspect API payloads without attaching a debugger to staging.
Pair this discipline with Redis caching patterns and multi-server session config so performance tuning and debugging stay in separate lanes. When upgrades break dev tooling, Rector and Composer autoloader optimisation address code-level regressions Xdebug will not catch alone.
Need a full dev environment built correctly from the start? See custom software development or web development services for Laravel, Symfony, and WordPress projects with sane defaults. Read more on the PHP and Laravel blog, review shipped portfolio work, or learn about Kokil's background in full-stack delivery since 2010.
Key Takeaways
- Set
xdebug.mode=debug, port 9003, andstart_with_request=trigger— then activate per request with a cookie or browser extension. - Install Xdebug for the same PHP binary your web SAPI uses; CLI-only installs fool almost everyone once.
- Fix Docker and WSL2 by pointing
xdebug.client_hostat the host gateway IP, not container localhost. - Mirror absolute paths exactly in VS Code
pathMappingsand PhpStorm server settings. - Never load Xdebug on production — use trigger mode on staging and keep profiling sessions short.
- Read
/tmp/xdebug.logat log level 7 before you rewrite working application code.
People Also Ask
What port does PHP Xdebug 3 use for IDE debugging?
Xdebug 3 defaults to port 9003, not 9000. VS Code, PhpStorm, and firewall rules must listen on 9003. Older tutorials referencing 9000 are written for Xdebug 2 and will fail silently if only the IDE port is wrong.
Why does Xdebug 3 not connect to VS Code?
The top three causes are wrong client_host in Docker, mismatched path mappings, and debugging through a PHP binary that lacks the extension. Confirm with php -i | grep xdebug on the FPM pool version and tail xdebug.log during a triggered request.
Should xdebug.start_with_request be yes or trigger?
Use trigger on any machine others share or that resembles staging. Use yes only on isolated local VMs when you want every request to attempt debugging without a browser extension. Trigger mode avoids accidental performance drain.
Does Xdebug 3 work with PHP 8.5 and Laravel 13?
Yes. Install the Xdebug build compiled for your exact PHP version from PECL or your distro package manager. Laravel 13 requires PHP 8.3 minimum; Laravel 12 runs on PHP 8.2. Match the extension to whichever version serves the app — the IDE side stays the same.
Ship Faster With Working Debug Tools
PHP Xdebug 3 configuration for modern IDEs boils down to mode, host, port, and paths. Get those four right once per environment and breakpoints become boring again — which is exactly what you want when you are tracing payment callbacks or queue jobs on a deadline. If your team loses hours to broken debug setups after PHP upgrades or Docker migrations, get in touch for environment hardening, or explore ongoing support and maintenance so production and dev stacks stay aligned.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

