How to Set Up Xdebug with Laravel Sail: A Complete Guide
Xdebug is a powerful tool for debugging PHP applications, offering more advanced features compared to basic debugging methods like dd()
or var_dump()
. With Xdebug, you can set breakpoints, inspect variables, step through code execution, and gain deep insight into the behavior of your application—all in real-time. In a Dockerized environment like Laravel Sail, setting up Xdebug can seem challenging, but this guide will walk you through the process, from basic setup to more advanced customizations.
This article assumes you are running Laravel with Sail
1. Setting Up Xdebug in Laravel Sail
Out of the box, Laravel Sail comes with Xdebug pre-installed, but it’s turned off by default. To enable Xdebug, you just need to modify the .env
file.
Step 0: Fix php.ini
According to the docs modify the .env
file is enough.
However, it seems that this part of the docs is currently plain wrong. The SAIL_XDEBUG_MODE
environment variable doesn't take effect out of the box because the default Sail configuration doesn't dynamically apply the variable in the container's php.ini
file. This has been an unresolved issue since 2022 (GitHub issue #357).
To ensure that SAIL_XDEBUG_MODE
works as intended, you need to publish and customize your php.ini
file.
Run the following command to publish the Sail Docker configuration:
php artisan sail:publish
After publishing, locate the php.ini
file in the docker
directory. Check your docker-compose.yml
for the PHP version used in your Sail container (e.g., 8.2
).
Go then to ./docker/8.2/php.ini
and add this
Now changes to the variable SAIL_XDEBUG_MODE
does actually take effect.
After this change, you need to rebuild your container
./vendor/bin/sail down
./vendor/bin/sail build --no-cache
Step 1: Enable Xdebug
Open your .env
file and add or modify the following line to enable Xdebug:
SAIL_XDEBUG_MODE=debug
This will enable Xdebug in debug mode for your Sail environment.
By default, your docker-compose.yml file should look like this:
Meaning if you don’t specify SAIL_XDEBUG_MODE
xDebug is turned off.
Step 2: Rebuild and Restart Sail
Once you’ve updated your .env
file, you need to restart your Sail container (rebuild is not needed, restart is enough!):
./vendor/bin/sail down
./vendor/bin/sail up
This will apply the changes, and Xdebug should now be active.
2. Verifying Xdebug is Running
To verify that Xdebug is running, you can create a simple route in your Laravel application to show the current PHP configuration:
Route::get('/xdebug', function () { xdebug_info(); });
Visit /xdebug
in your browser, if you see this, it is working. It shows you also all configuration settings.
Alternatively, you can verify Xdebug from the command line inside the Sail container:
./vendor/bin/sail shell
php -i | grep xdebug
This should output details about Xdebug’s configuration and confirm that it’s running.
Validate the configuration, xdebug.mode
should be set to debug
:
And client_host
and client_port
should look like this:
If you running an old Docker version pre 20.10, you have to assign a static ip to the client host, as host.docker.internal
is only supported since Docker 20.10
(This setting works for Ubuntu aswell!).
3. Configuring PhpStorm for Xdebug
Once Xdebug is running, the next step is to configure PhpStorm to listen for Xdebug connections.
Step 1: Set the Debugger Port
Go to Settings > Languages & Frameworks > PHP > Debug and set the debug port to 9003
(the default for Xdebug 3).
Step 2: Set Up a PHP Server
In Settings > PHP > Servers, add a new server configuration:
- Name:
0.0.0.0
- Host:
0.0.0.0
- Port:
80
- Use path mappings: Check this box and map the server path (usually
/var/www/html
) to your local project directory.
Step 3: Install the Xdebug Helper Browser Extension
Since Laravel Sail uses start_with_request=default
by default, you'll need to manually trigger Xdebug when making requests. One of the easiest ways to do this is by using the Xdebug Helper browser extension:
- Install the Xdebug Helper extension for your browser (available for Chrome and Firefox).
- When you’re ready to debug, enable “Debug” mode in the extension before making a request, and Xdebug will start when you load the page.
Note: If you want to trigger Xdebug without the browser extension (by using URL parameters or modifying the configuration), see Step 5 for more details.
Step 4: Listen for Xdebug Connections
Click the “Start Listening for PHP Debug Connections” button (a bug icon in the top right corner) to enable PhpStorm to listen for incoming Xdebug connections.
4. Basic Debugging in Laravel
With Xdebug running and PhpStorm set up, you can now start debugging your Laravel application.
- Set breakpoints in your code by clicking on the line number in PhpStorm.
- Reload the page in your browser, and PhpStorm should catch the breakpoint and pause execution.
If Xdebug doesn’t stop at your breakpoints, revisit the settings from Step 2 and Step 3 to ensure the port and server configuration are correct.
5. Still not working? Try those settings:
Key PhpStorm Settings for Xdebug Debugging
To ensure a smooth debugging experience in PhpStorm, you’ll want to configure two important settings under Settings > PHP > Debug:
- Break at First Line in PHP Scripts:
- When to enable: This option causes Xdebug to break at the first line of every PHP script automatically. Enable it if you’re troubleshooting from the very beginning of your code. This makes sure xdebugs triggers, even if it never reases teh code where you set the breakpoint.
- When to disable: Disabling this option allows Xdebug to only stop at specific breakpoints you’ve set. This is useful when you are sure xdebug works.
- You can toggle this setting under Settings > PHP > Debug > Break at first line in PHP scripts.
- Ignore External Connections Through Unregistered Server Configurations:
- When to enable: This option prevents Xdebug from catching external connections when there is no registered server configuration in PhpStorm. This is useful for avoiding confusion when PhpStorm encounters requests that aren’t mapped to a server. Mabe you need to use something else instead of
0.0.0.0
? - When to disable: If you are sure xDebug is setup correctly, you may disable it.
- You can find this option in Settings > PHP > Debug as Ignore external connections through unregistered server configurations.
- Tip: During initial setup and testing, it can be helpful to leave “Break at first line in PHP scripts” checked and “Ignore external connections” unchecked.
6. Customizing Xdebug Behavior: start_with_request=default
vs. yes
By default, Laravel Sail configures Xdebug with start_with_request=default
, meaning Xdebug only starts a debug session when explicitly triggered (e.g., through a browser extension like Xdebug Helper). However, you can customize Xdebug to automatically start on every request by changing the start_with_request
setting.
Understanding the Default Behavior (start_with_request=default
)
- How it works: Xdebug waits for an explicit trigger (e.g., the Xdebug Helper browser extension or the
XDEBUG_SESSION_START
URL parameter) before starting a debug session. This setup improves performance by avoiding debugging overhead on every request.
Switching to start_with_request=yes
If you want Xdebug to start debugging automatically on every request (without needing the browser extension or URL parameter), you can switch to start_with_request=yes
but be aware, this may slow down your machine performance.
How to Change the Setting:
- Publish Sail’s Docker Configuration:
./vendor/bin/sail artisan sail:publish
2. Update the php.ini
File: In the published configuration folder (docker/8.2/php.ini
), update the Xdebug settings:
[XDebug]
zend_extension = xdebug.so
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.discover_client_host = true
xdebug.idekey = PHPSTORM
xdebug.client_host = host.docker.internal
xdebug.client_port = 9003
3. Rebuild and Restart Sail:
With this setting, Xdebug will automatically start a debug session for every request, which can simplify debugging but may slightly reduce performance during development.
Note: If you prefer the default behavior and want to selectively trigger debugging using the Xdebug Helper browser extension or URL parameters, you can leave
start_with_request=default
unchanged.