Xdebug — Debugging & Profiling
debt(d7/e3/b3/t7)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints list phpunit and phpstan as tools, but neither catches Xdebug being enabled in production php.ini as a default rule. The code_pattern notes 'xdebug enabled in production php.ini' — this requires inspecting server configuration or deployment scripts, which is typically caught only through code review of infrastructure files or noticing performance degradation in production. Not d9 because a careful deployment review or CI environment check can surface it.
Closest to 'simple parameterised fix' (e3). The quick_fix is essentially editing php.ini or environment configuration to set correct xdebug.mode values and remove the extension from production. This is slightly more than a one-line patch (e1) because it touches php.ini, possibly deployment scripts, and CI configuration, but it doesn't span multiple application files — it's a localised configuration change.
Closest to 'localised tax' (b3). Xdebug is a developer tooling choice that primarily affects the local development and CI environment. It applies to web and cli contexts but its misuse (being left in production) is a configuration/ops concern, not a structural burden that shapes every future feature. The rest of the codebase is unaffected once correctly configured.
Closest to 'serious trap' (t7). The misconception field explicitly states developers believe Xdebug can be left enabled in production for emergency debugging. This contradicts the mental model of 'emergency debug tools are safe if rarely used' that developers carry from other ecosystems or local usage. The up to 10x performance overhead and exposure of stack traces are non-obvious consequences that a competent developer unfamiliar with Xdebug's production impact would likely miss.
Also Known As
TL;DR
Explanation
Xdebug is the standard PHP debugging and profiling tool. It integrates with IDEs (PhpStorm, VS Code) via DAP (Debug Adapter Protocol) for step-through debugging, variable inspection, and breakpoints. In profiling mode it generates cachegrind files readable by KCacheGrind or WebGrind. It powers PHPUnit's code coverage reports (requires xdebug.mode=coverage). Key modes: debug (step debugging), profile (performance analysis), trace (full execution trace), coverage. Never run Xdebug in production — it adds significant overhead and exposes a remote debugging port.
Watch Out
Common Misconception
Why It Matters
Common Mistakes
- Installing Xdebug in production — it adds significant overhead and exposes debug endpoints.
- Not configuring xdebug.mode = debug,coverage in php.ini — leaving it on develop mode without specific mode misses features.
- Not setting xdebug.start_with_request = trigger — without it, every request tries to connect to the debugger.
- Using var_dump as a substitute for a debugger — Xdebug step debugging shows the full call stack and variable state at any point.
Avoid When
- Never install Xdebug on a production server — it significantly degrades performance and exposes debugging interfaces.
- Disable xdebug.remote_enable and xdebug.mode=off in any non-development environment.
When To Use
- Use Xdebug in local development for step debugging, profiling, and code coverage.
- Use Xdebug's profiler output with KCacheGrind/QCacheGrind to identify performance bottlenecks.
Code Examples
; php.ini — Xdebug in production:
[xdebug]
zend_extension=xdebug.so
xdebug.mode=develop,debug
xdebug.start_with_request=yes ; Every request tries to debug — massive overhead
xdebug.client_host=localhost ; Should never be active in production
; Xdebug 3 configuration
[xdebug]
zend_extension = xdebug
xdebug.mode = debug,coverage
xdebug.start_with_request = trigger ; activate only when triggered (not every request)
xdebug.client_host = host.docker.internal
xdebug.client_port = 9003
; VS Code step debugging:
; 1. Install PHP Debug extension
; 2. Set breakpoint
; 3. Start listening (F5)
; 4. Trigger request with XDEBUG_SESSION cookie or ?XDEBUG_SESSION=1
; Code coverage (PHPUnit):
$ phpunit --coverage-html=coverage/
; Requires xdebug.mode = coverage