Software Development

Setting up PHP Debugging with Lumen, XDebug, PHPUnit, and Visual Studio Code using Docker

If you are trying to keep your development environment contained in docker containers, but are having some issues getting debugging working with XDebug, VSCode, and a PHPUnit XML configuration file this article may help you.

TLDR;

You have to set xdebug.remote_host setting in the PHP-FPM Docker container to your host machine’s IP. This is due to the nature of XDebug. Starting the PHP Debugger plugin in VSCode is actually starting  XDebug’s Client which will listen for events from the XDebug server, which is the place the PHP is being executed. We want to execute our PHP in our PHP-FPM Docker container, so we have to specify the IP of the remote_host (which is our host machine) we want to send XDebug events to. This part of the XDebug documentation details how XDebug remote debugging works.

Install PHP Debug VS Code Plugin

If you’re reading this, you’ve probably already done this. But in case not, head to the VS Code PHP Debug Plugin Page to install the PHP Debug plugin.

Stack/Container Overview

  • PHP7.2
  • Nginx
  • Postgres

You can use the following repo as a reference or as a template for your project:
https://github.com/amanos1022/lumen-docker-lepp/

Follow the steps in the README.md before continuing. Or at least review my docker-compose.yml file so we’re on the same page in terms of container setup. After you have all your containers up and running, we have to set the xdebug.remote_host setting to equal your host machine’s IP address in the PHP-FPM Docker container.


Note on why setting xdebug.remote_connect_back=1 doesn’t work in this case: 
We are going to be executing our PHP code in the PHP-FPM Docker container, but the XDebug client is going to be listening for XDebug events on our host machine via VSCode’s PHP Debug Plugin. For remote_connect_back to work, we’d have to be executing the PHP on the same machine that is running the XDebug client (our host machine running VSCode’s Debugger in this case). But that would mean we’d have to execute the PHP script on our host machine which defeats the purpose of using Docker for our development environment. See XDebug’s documentation on remote debugging for more info on how all this works.

Get into the php container’s shell:

docker exec -it my-api-php sh

once in there, retrieve your host machine’s ip by running:

#should output something like 172.10.0.1
/sbin/ip route|awk '/default/ { print $3 }'

And set that IP address as the xdebug.remote_host in /usr/local/etc/php/conf.d/xdebug.ini (convenienty, this PHP-FPM image has vi installed). It should look something like this when you’re done:

zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20170718/xdebug.so
xdebug.remote_enable=1
xdebug.remote_autostart=1
xdebug.remote_host=YOUR_HOST_MACHINES_IP
xdebug.remote_port=9000

“reload” php:

kill -USR2 1

Open the root of your application in VS Code, open the debug panel (CTRL/CMD+Shift+D) and click the drop down next to the green play button and select “Add Configuration…” Select PHP. A new tab will open in VSCode which is the launch.json file. The only modification you’ll have to make is adding the pathMappings property in the launch.json file like so:

{
    "name": "Listen for XDebug",
    "type": "php",
    "request": "launch",
    "port": 9000,
    "pathMappings": {
        "/app" : "${workspaceRoot}"
    }
},

/app is the directroy the application lives in on the Docker container, and ${workspaceRoot} is the directory you have open in VSCode.

Running the debugger

Wer’re just going to use the ExampleTest.php that comes with Lumen so we don’t have to go over configuring PHPUnit. Set a breakpoint (F9) on line 15 or whatever the first line of the testExample method in the ExampleTest class is.

Start a debug session(F5) in VS Code by pressing the green play button in the debug panel. Make sure you use “Listen For XDebug” as the debug setting. This starts the XDebug client to listen for events from the XDebug server, which won’t be fired until we run some PHP code on our server (i.e. our PHP-FPM Docker container). In our case, this will be running the phpunit command in the root of our project like so:

#still in the PHP-FPM Docker container's shell
cd /app
./vendor/bin/phpunit

And there you have it! Your code should have stopped executing at the breakpoint you set, and you should be able to see variables and other information in VSCode’s debug panel. You also have the ability to step over/into the line of code you are at. Happy debugging!

Angelo Manos

I am a Software Developer based in San Diego, California. I also write and preform music, and do all sort of different art including canvases, airbrushing, and murals.

Leave a Reply

Your email address will not be published. Required fields are marked *