code quality and tooling
Xdebug Basics
Xdebug is powerful, but it is configuration-sensitive. The first skill is understanding the moving parts rather than copying old settings from random examples.
Check whether Xdebug is installed
Use PHP itself to check loaded extensions.
php -m | grep xdebug
You can also ask PHP for Xdebug information:
php --ri xdebug
If Xdebug is not installed, these commands will not show the extension.
Xdebug has modes
Modern Xdebug uses xdebug.mode to decide which features are active.
Common modes include:
developfor improved development diagnosticsdebugfor step debuggingcoveragefor code coverage toolsprofilefor profiling performancetracefor function traces
For step debugging, the important mode is debug.
xdebug.mode=debug,develop
Do not enable every mode all the time. Extra modes can slow PHP down, especially coverage and profiling.
Step debugging needs an IDE listener
Xdebug does not open a debugger screen by itself. It connects from PHP to a debug client, usually your IDE or editor.
The default Xdebug 3 debug port is 9003.
xdebug.client_port=9003
Your IDE must be listening on the same port. If PHP says it tried to connect but failed, check the IDE listener, port, firewall, container networking, and host settings.
Starting a debug request
For local learning, a simple configuration might start debugging on every request.
xdebug.mode=debug,develop
xdebug.start_with_request=yes
xdebug.client_host=127.0.0.1
xdebug.client_port=9003
In larger projects, xdebug.start_with_request=trigger is often better because it starts debugging only when a trigger is present. That avoids slowing every request.
CLI debugging
Xdebug can debug command-line scripts too. The IDE still needs to listen for the incoming debug connection.
XDEBUG_MODE=debug php discount.php
Environment variables are useful when you do not want debug mode enabled for every PHP command.
What a breakpoint does
A breakpoint tells the debugger to pause on a line. Once paused, you can inspect variables, step over the next line, step into a function, continue to the next breakpoint, or stop the session.
Use this kind of small script to practise.
<?php
declare(strict_types=1);
function discountForSubtotal(int $subtotal): int
{
if ($subtotal >= 5000) {
return 500;
}
return 0;
}
$subtotal = 5000;
$discount = discountForSubtotal($subtotal);
echo $discount . PHP_EOL;
// Prints:
// 500
Set a breakpoint on the line that calls discountForSubtotal(), then step into the function and inspect $subtotal.
Common setup problems
Most Xdebug problems are not PHP logic problems. They are connection problems.
Check these first:
- is Xdebug installed for the same PHP binary or container that runs the code?
- does
xdebug.modeincludedebug? - is the IDE listening?
- does the IDE use port
9003? - is
xdebug.client_hostcorrect for the machine or container? - does
xdebug.start_with_requestmatch how you are triggering the session? - are path mappings correct when running inside Docker, WSL, Vagrant, or a remote server?
Path mappings matter because the file path inside the container may not be the same as the file path on the host machine.
What Xdebug is not
Xdebug does not replace tests, logs, stack traces, or careful reasoning. It helps you inspect runtime state. You still need to understand what the code should do and how to verify the fix afterward.
Before moving on, make sure you can explain xdebug.mode, xdebug.start_with_request, xdebug.client_host, xdebug.client_port, and why the IDE must listen for a debug connection.
Practice
Task: Write An Xdebug CLI Checklist
Write a short Xdebug setup checklist for debugging a local CLI script.
Requirements
- Include the command to check whether Xdebug is loaded.
- Include the minimum Xdebug mode needed for step debugging.
- Include the default Xdebug 3 debug port.
- Include the command to run
discount.phpwith debug mode enabled for that command. - Include one likely reason breakpoints might not be hit.
Show solution
php -m | grep xdebug
Step debugging needs debug mode:
xdebug.mode=debug
The default Xdebug 3 debug port is:
xdebug.client_port=9003
Run a CLI script with debug mode enabled for that command:
XDEBUG_MODE=debug php discount.php
If breakpoints are not hit, a likely cause is that the IDE is not listening on port 9003, or the PHP process is running somewhere with different file paths and the IDE path mapping is wrong.