About us Guides Projects Contacts
Админка
please wait

Xdebug is an essential tool for PHP developers, providing step debugging, profiling, and code coverage capabilities. While var_dump and logging have their place, nothing beats proper debugging for understanding complex code flows. This guide covers setting up and using Xdebug effectively from a senior developer's perspective.

Why Xdebug

Xdebug transforms PHP development:

  1. Step Debugging: Set breakpoints, inspect variables, step through code
  2. Profiling: Find performance bottlenecks with detailed timing data
  3. Stack Traces: Get meaningful error traces with local variables
  4. Code Coverage: Measure test coverage accurately
  5. IDE Integration: Works with PhpStorm, VS Code, and other editors

Warning: Never enable Xdebug on production servers—it significantly impacts performance.

Installation

Standard Installation

# Using PECL
pecl install xdebug
# On Ubuntu/Debian
sudo apt install php-xdebug
# On CentOS/RHEL
sudo dnf install php-pecl-xdebug

Installation in Docker

Add to your development Dockerfile:

FROM php:8.2-fpm
# Install Xdebug
RUN pecl install xdebug \
&& docker-php-ext-enable xdebug
# Copy Xdebug configuration
COPY xdebug.ini $PHP_INI_DIR/conf.d/xdebug.ini

Create xdebug.ini:

[xdebug]
zend_extension=xdebug
; Enable step debugging
xdebug.mode=debug
xdebug.start_with_request=trigger
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.idekey=PHPSTORM
; Optionally enable profiling
; xdebug.mode=debug,profile
; xdebug.output_dir=/var/www/html/profiles

For Docker Compose, ensure proper networking:

version: '3.8'
services:
php:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- ./:/var/www/html
environment:
- PHP_IDE_CONFIG=serverName=docker
extra_hosts:
- "host.docker.internal:host-gateway"

Xdebug 3 Configuration Modes

Xdebug 3 uses modes to control features. Set via xdebug.mode:

ModeDescription
offNothing is enabled (default)
developDevelopment aids (var_dump improvements)
debugStep debugging
profileProfiling
coverageCode coverage
traceFunction trace

Combine modes with commas:

xdebug.mode=debug,profile,coverage

Step Debugging Setup

Configuration for Debugging

Create or edit xdebug.ini:

[xdebug]
zend_extension=xdebug
xdebug.mode=debug
xdebug.start_with_request=trigger
xdebug.client_host=127.0.0.1
xdebug.client_port=9003
xdebug.idekey=PHPSTORM
xdebug.log=/tmp/xdebug.log

Trigger Methods

With startwithrequest=trigger, debugging starts when:

  1. GET/POST parameter: ?XDEBUGSESSIONSTART=PHPSTORM
  2. Cookie: XDEBUG_SESSION=PHPSTORM
  3. Browser extension: Xdebug Helper for Chrome/Firefox

PhpStorm Configuration

  1. Go to Settings → PHP → Debug
  2. Set Debug port to 9003
  3. Enable "Can accept external connections"
  4. Go to Settings → PHP → Servers
  5. Add a server with path mappings for Docker:

- Name: docker - Host: localhost - Port: 80 - Debugger: Xdebug - Path mappings: /local/path/var/www/html

VS Code Configuration

Install the PHP Debug extension, then create .vscode/launch.json:

{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/html": "${workspaceFolder}"
}
},
{
"name": "Launch currently open script",
"type": "php",
"request": "launch",
"program": "${file}",
"cwd": "${fileDirname}",
"port": 9003
}
]
}

Debugging CLI Scripts

For command-line PHP scripts:

# Set the environment variable
export XDEBUG_SESSION=1
php artisan my:command
# Or inline
XDEBUG_SESSION=1 php script.php

Performance Profiling

Enable Profiling

Configure for on-demand profiling:

[xdebug]
zend_extension=xdebug
xdebug.mode=profile
xdebug.start_with_request=trigger
xdebug.output_dir=/var/www/html/profiles
xdebug.profiler_output_name=cachegrind.out.%p.%t

Trigger profiling by adding ?XDEBUG_PROFILE to any URL:

http://localhost/api/users?XDEBUG_PROFILE

Analyzing Profile Data

Profile files use cachegrind format. Analyze with:

KCachegrind (Linux/macOS):

# Install
sudo apt install kcachegrind # Ubuntu
brew install qcachegrind # macOS
# Open profile
kcachegrind profiles/cachegrind.out.12345

Webgrind (Web-based):

# Clone Webgrind
git clone https://github.com/jokkedk/webgrind.git
# Point the web server to the Webgrind folder
# Access via http://localhost/webgrind

Reading Profiler Output

Key metrics to analyze:

  1. Self Time: Time spent in the function itself
  2. Inclusive Time: Time including called functions
  3. Call Count: Number of times the function was called

Focus on:

  • Functions with high self time (optimization targets)
  • Functions called excessively (potential N+1 queries)
  • Unexpected function calls (debugging)

Profiling Best Practices

// Profile specific code sections
xdebug_start_profiling();
// Your code here
$result = expensiveOperation();
xdebug_stop_profiling();

Code Coverage

Configure for Coverage

[xdebug]
xdebug.mode=coverage

PHPUnit Integration

<!--phpunit.xml-->
<phpunit>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
<exclude>
<directory>./vendor</directory>
</exclude>
<report>
<html outputDirectory="coverage-report"/>
<text outputFile="coverage.txt"/>
</report>
</coverage>
</phpunit>

Run with coverage:

php artisan test --coverage
# or
./vendor/bin/phpunit --coverage-html coverage-report

Development Aids

Enhanced var_dump

With xdebug.mode=develop:

$data = ['users' => [
['name' => 'John', 'email' => '[email protected]'],
['name' => 'Jane', 'email' => '[email protected]'],
]];
var_dump($data); // Now shows colored, formatted output

Stack Traces

Xdebug enhances error stack traces automatically:

function level3() {
throw new Exception("Something went wrong");
}
function level2() {
level3();
}
function level1() {
level2();
}
level1(); // Stack trace shows all levels with local variables

Troubleshooting

Verify Installation

<?php
phpinfo(); // Look for the Xdebug section
// or
php -v // Should show "with Xdebug"

Check Configuration

php -i | grep xdebug

Common Issues

Connection refused:

  • Verify the IDE is listening on the correct port
  • Check firewall rules
  • Ensure client_host is correct (use host.docker.internal for Docker)

Debugging doesn't start:

  • Check xdebug.mode includes debug
  • Verify the trigger method (cookie, GET parameter)
  • Review the Xdebug log: xdebug.log=/tmp/xdebug.log

Path mapping issues:

  • Ensure the IDE server configuration matches actual paths
  • For Docker, map container paths to local paths

Performance impact:

  • Use startwithrequest=trigger instead of yes
  • Disable Xdebug when not needed
  • Never use in production

Docker-Specific Issues

If host.docker.internal doesn't work:

# docker-compose.yml
services:
php:
extra_hosts:
- "host.docker.internal:host-gateway"

Or use your host machine's IP address directly in xdebug.client_host.

Multi-Mode Configuration

For development environments needing all features:

[xdebug]
zend_extension=xdebug
; Enable multiple modes
xdebug.mode=debug,develop,coverage
; Debugging settings
xdebug.start_with_request=trigger
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.idekey=PHPSTORM
; Profiling (enable mode when needed)
; xdebug.mode=profile
xdebug.output_dir=/tmp/xdebug
xdebug.profiler_output_name=cachegrind.out.%p
; Logging
xdebug.log=/tmp/xdebug.log
xdebug.log_level=3

Key Takeaways

  1. Use trigger mode: Don't enable debugging for all requests
  2. Profile before optimizing: Find real bottlenecks; don't guess
  3. Configure path mappings: Essential for Docker and remote debugging
  4. Never use in production: Performance impact is significant
  5. Leverage IDE features: Breakpoints, watches, and call stacks
  6. Check the log: When debugging fails, Xdebug logs tell you why

Xdebug transforms PHP debugging from frustrating print statements to a professional development workflow. Master it, and you'll solve complex bugs in minutes instead of hours.

 
 
 
Языки
Темы
Copyright © 1999 — 2026
ZK Interactive