Xdebug 3 changed the configuration approach – instead of many directives, one option xdebug.mode controls all behaviour. Combining Xdebug 3, DDEV and PHPStorm gives a complete environment: step debugger with breakpoints, a profiler generating cachegrind files, and coverage reports for PHPUnit. I show the configuration from scratch and how to analyse profiler results in PHPStorm and QCacheGrind.
Xdebug 3 – modes and configuration
; Xdebug 3 - everything controlled by xdebug.mode ; Possible values (can be combined with commas): ; off - disabled ; develop - improved var_dump, stack traces ; coverage - code coverage for PHPUnit ; debug - step debugger ; gcstats - garbage collector statistics ; profile - profiler (generates cachegrind) ; trace - function trace ; Minimal configuration for debugging xdebug.mode = debug xdebug.start_with_request = yes xdebug.client_host = host.docker.internal xdebug.client_port = 9003 xdebug.log = /var/log/xdebug.log xdebug.log_level = 7
Configuration in DDEV
# DDEV has built-in Xdebug support ddev xdebug on ddev xdebug off ddev xdebug status # DDEV automatically configures: # - xdebug.client_host = host.docker.internal # - xdebug.client_port = 9003 # - Firewall rules for the connection # Custom configuration: .ddev/php/xdebug.ini # xdebug.mode = debug,profile # xdebug.start_with_request = trigger # xdebug.output_dir = /var/www/html/xdebug # xdebug.profiler_output_name = cachegrind.out.%p.%H ddev restart # after changing .ini files
PHPStorm – connection configuration
# 1. PHPStorm: Settings > PHP > Debug # Debug port: 9003 # Check: "Can accept external connections" # 2. Settings > PHP > Servers # Name: ddev # Host: magento-shop.ddev.site # Port: 443 # Debugger: Xdebug # Use path mappings: YES # /var/www/html -> /Users/henryk/projects/magento-shop # 3. Run > Start Listening for PHP Debug Connections # 4. Set a breakpoint in PHP code # 5. Open URL with XDEBUG_SESSION=1 parameter # https://magento-shop.ddev.site/?XDEBUG_SESSION=1 # or use browser extension: Xdebug Helper # 6. PHPStorm will stop at the breakpoint
Step debugger – commands
# PHPStorm commands during a debug session: # F8 - Step Over (execute line, don't enter function) # F7 - Step Into (enter function) # F9 - Resume (continue to next breakpoint) # Shift+F8 - Step Out (exit function) # Useful when debugging Magento 2: # - Watches: add PHP expressions to observe # - Evaluate: execute any PHP expression in current context # - Variables panel: view all variables # Conditional breakpoint (right-click breakpoint): # $order->getGrandTotal() > 1000.0
Profiler – performance analysis
# .ddev/php/xdebug.ini for profiling # xdebug.mode = profile # xdebug.output_dir = /var/www/html/xdebug/profiles # xdebug.profiler_output_name = cachegrind.out.%p # Trigger profiling via URL parameter: # https://magento-shop.ddev.site/catalog/category/view/id/3?XDEBUG_PROFILE=1 # Copy file from container: ddev exec ls /var/www/html/xdebug/profiles/ ddev exec cat /var/www/html/xdebug/profiles/cachegrind.out.42 > ./cachegrind.out.42
Cachegrind analysis in PHPStorm
# PHPStorm: Tools > Analyze Xdebug Profiler Snapshot # Open cachegrind.out.XX file # PHPStorm Profiler views: # - Execution Statistics: function list with self and total time # - Call Tree: call tree with times # - Flame Graph: hot spot visualisation (PHPStorm 2023+) # What to look for: # - Self time: time in this function only (without called functions) # - Total time: total time including calls # - Calls: call count - 10000 calls * 0.1ms = 1s! # Typical hot spots in Magento 2: # - \Magento\Framework\App\Config\ScopeConfigInterface::getValue # (too many calls - cache config in your service) # - \Magento\Framework\Interception\Interceptor::__callPlugins # (too many around plugins) # - Collections without setPageSize() # (loading entire table)
Code coverage in PHPUnit
# .ddev/php/xdebug.ini
# xdebug.mode = coverage
ddev exec vendor/bin/phpunit \
--coverage-html coverage-report \
--coverage-clover coverage.xml \
app/code/Vendor/Module/Test/Unit
# Open coverage-report/index.html in browser
# PHPStorm: Run > Show Code Coverage Data
# Load coverage.xml for inline coverage in editor
Summary
Xdebug 3 with DDEV is a one-command installation with zero manual IP configuration. Mode debug for the step debugger, profile for performance analysis, coverage for tests. PHPStorm with PHPStorm Profiler and Flame Graph lets you find hot spots quickly. In Magento 2 the most common performance issues are too many ScopeConfig::getValue calls, collections without a limit, and excessive around plugins.
