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:

  • develop for improved development diagnostics
  • debug for step debugging
  • coverage for code coverage tools
  • profile for profiling performance
  • trace for 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 example
<?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.mode include debug?
  • is the IDE listening?
  • does the IDE use port 9003?
  • is xdebug.client_host correct for the machine or container?
  • does xdebug.start_with_request match 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.php with 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.