Xdebug is the standard PHP debugging and profiling extension. It transforms PHP development from var_dump()-driven debugging into a full interactive debugging experience with step-through execution, breakpoints, variable inspection, call stack navigation, and code coverage analysis for unit tests. Xdebug 3 introduced a simplified configuration model that replaces the complex Xdebug 2 settings with a single xdebug.mode directive that enables specific capabilities on demand: debug (step debugging), profile (performance profiling), coverage (code coverage for PHPUnit), and trace (execution trace logging). This guide covers installing Xdebug 3 on RHEL 9, configuring it for VS Code step debugging with the PHP Debug extension, and running code coverage analysis with PHPUnit.

Prerequisites

  • PHP 8.x installed on RHEL 9
  • A PHP project (e.g., Laravel, Symfony, or plain PHP)

Step 1 — Install Xdebug

# Install from Remi repo (ensures compatibility with the installed PHP version)
dnf install -y php-pecl-xdebug3

# Verify Xdebug is loaded
php -m | grep xdebug
php --ri xdebug | head -5

Step 2 — Configure Xdebug for Step Debugging

# /etc/php.d/15-xdebug.ini
[xdebug]
zend_extension=xdebug.so

; Enable step debugging mode
xdebug.mode = debug

; Wait for an IDE to connect on each request (use 'trigger' in production)
xdebug.start_with_request = yes

; IDE host — for VS Code on the same machine
xdebug.client_host = 127.0.0.1
xdebug.client_port = 9003

; Log file for troubleshooting connection issues
xdebug.log = /tmp/xdebug.log
xdebug.log_level = 3

; IDE key (used by VS Code PHP Debug extension)
xdebug.idekey = VSCODE
systemctl restart php-fpm

Step 3 — Configure VS Code for PHP Debugging

# Install the PHP Debug extension in VS Code:
# Extensions → search "PHP Debug" by Xdebug → Install

# .vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for Xdebug",
            "type": "php",
            "request": "launch",
            "port": 9003,
            "pathMappings": {
                "/var/www/myapp": "${workspaceFolder}"
            }
        }
    ]
}
# Usage:
# 1. Set a breakpoint in VS Code (click left of line number)
# 2. Press F5 to start listening
# 3. Open the PHP page in a browser — execution halts at the breakpoint

Step 4 — Profiling Mode

# Enable profiling (generates cachegrind files)
; In /etc/php.d/15-xdebug.ini:
xdebug.mode = profile
xdebug.output_dir = /tmp/xdebug_profiles
xdebug.profiler_output_name = cachegrind.out.%p

# Analyse with KCachegrind or PHP webgrind
dnf install -y kcachegrind    # Desktop only
# Or use webgrind for web-based analysis:
# https://github.com/jokkedk/webgrind

Step 5 — Code Coverage with PHPUnit

# Enable coverage mode
; In /etc/php.d/15-xdebug.ini:
xdebug.mode = coverage
# Run PHPUnit with HTML coverage report
./vendor/bin/phpunit --coverage-html /var/www/myapp/coverage-report

# Open /var/www/myapp/coverage-report/index.html in a browser

Conclusion

Xdebug 3 on RHEL 9 provides professional-grade PHP debugging capabilities. The key production safety rule: never enable Xdebug in production with xdebug.start_with_request = yes — every PHP request will wait for an IDE connection, causing severe performance degradation and timeouts. For production servers where occasional profiling is needed, use xdebug.start_with_request = trigger and initiate profiling by appending ?XDEBUG_PROFILE=1 to a request. Xdebug should be installed only on development and staging servers.

Next steps: How to Install PHP 8.3 on RHEL 9, How to Harden PHP on RHEL 9, and How to Install PHPUnit on RHEL 9.