September 9, 2022 - 7 min

Xdebug for PHP developers - PhpStorm and Docker


				
				

Tomislav Cipric

Xdebug allows you to break code execution to see the state/value of the current instantiated variables/objects, test object methods, and pass through all logical steps.


It also allows you to modify variables/objects on the fly, affecting the execution of your script during one iteration and running cycle.  What this means is you have everything you need to troubleshoot and track down the issues and be more efficient.


Many PHP IDEs support Xdebug integration but in this text, I will be explaining how to configure Xdebug on a PhpStorm running with Docker.


Installation


 


To run it you need to install and integrate the Xdebug extension. Basic installation is mostly done using pecl (package with repository for PHP extensions).


Our dev environment will be run inside docker containers, so we need to add an installation command inside Dockerfile.



RUN pecl install xdebug


Enable the Xdebug extension must be added to php.ini or any custom ini you want to use as an addition to the default PHP ini files.


Basic configuration for Xdebug 3:



#enabling extension

zend_extension=xdebug.so

#setting xdebug working mode. In version 3, you can specify multiple modes separated by comma 

xdebug.mode = debug

#If enabled, this setting will activate the discovery of the client's IP address. It's set to 0 because we are going to use the static IP address of the host IP running Docker.

xdebug.discover_client_host=0

#static IP address of the host machine from docker container for OsX and Windows use host.docker.internal

xdebug.client_host=172.17.0.1

#default xdebug 3 port

xdebug.client_port = 9003

#PHP IDE trigger key if set, for example, in request URL, it will trigger activation of xdebug

xdebug.idekey = PHPSTORM

#setting the limit of how deep nesting/recurring requests can go 

xdebug.max_nesting_level = 12256

#logging file for xdebug where we can see the details of xdebug execution or check if xdebug is not working correctly

xdebug.log = /app/var/log/xdebugaa.log

#activating Xdebug before each PHP request (helpful when debugging PHP execution from console)

xdebug.start_with_request=yes


Find more xdebug settings on: https://xdebug.org/docs/all_settings


Basic configuration for Xdebug 2:



#enabling extension

zend_extension=xdebug.so

#enabling xdebug debug mode

xdebug.remote_enable=1

#activating xdebug before each PHP request

xdebug.remote_autostart=1

#PHP IDE trigger key if set for example in request url, it will trigger activation of xdebug

xdebug.idekey=PHPSTORM

#setting the limit of how deep nesting/recurring request can go

xdebug.max_nesting_level=120000

#if enabled, this setting will activate the discovery of the client's IP address. It is set to 0 because I will use the static IP address of the host IP running Docker.

xdebug.remote_connect_back=0

#default xdebug 2 port

xdebug.remote_port=9000

#static IP address of the host machine from docker container for OsX and Windows use host.docker.internal

xdebug.remote_host=172.17.0.1


To check if xdebug is configured correctly with PHP, run the command inside the container where the PHP instance is running.



Php ‚Äďinfo | grep xdebug


You should get a similar response:



Xdebug configuration details in PHP info


Don’t forget to restart the docker container after making changes in your local xdebug.ini file.



Configuring Xdebug on PhpStorm


 


Open PhpStorm and go to the menu and open the Settings dialog. In the Settings dialog, choose PHP on the left list. On the right part of the dialog, you will see PHP project settings. 



PHP settings dialog


 


Setting up PHP CLI interpreter


 


To configure the CLI interpreter, press … (three dots) on the right side of the CLI interpreter line.



In the CLI interpreters dialog, click on + in the upper left corner and choose to set PHP interpreter from Docker.



 


We need to set the interpreter from our docker-compose configuration file. The first step is creating a Docker connection. If you don’t have a pre-filled Docker server, click the¬†NEW‚Ķ¬†button in the upper right corner.



Remote PHP interpreter configuration dialog


 


Name the docker connection as you wish, select Unix socket if you use Linux as your OS, and press OK.



 Docker connection configuration dialog


 


When you return to the previous interpreter dialog, you must set a local path to the docker-compose.yml file. When you set the docker-compose path, the Service selector will be filled with the services available in your docker-compose config file.



Remote PHP interpreter configuration dialog with service selected


 


Please choose your PHP/web service (the one with a PHP instance), so IDE can read Xdebug configuration from the container. If your PHP path differs from the default one, you can change it in the PHP interpreter path section. When you are done, click on the OK button.


PHP interpreter dialog will appear.



PHP CLI interpreter configuration dialog


 


The Xdebug version should be automatically detected. If you don’t see it, click on the refresh button.


 


Setting up path mapping and server configuration


 


What is path mapping?


Path mapping will tell Xdebug the location/path of our project files in the Docker container or the remote server if we use Xdebug for remote debugging.


If we set a breakpoint and run the PHP script without setting proper path mapping, IDE will display an error with the message that path mapping is missing. This is because we are running our project in a docker container, which probably has a different path than our local project.



Xdebug – missing server path mapping configuration


 


I usually set the name of the server in the¬†PHP Docker service¬†environment configuration, as if you do not set it, the name of the host in the Xdebug connection will, by default, be “localhost.” Defining¬†serverName¬†in configuration will help you differentiate projects if you are working on two different projects at the same time.



Environment:

PHP_IDE_CONFIG: 'serverName=docker_symfony'

XDEBUG_CONFIG: 'idekey=PHPSTORM'


Docker-compose.yml PHP service environment configuration 


To set server configuration, we can click on the error link or open Settings -> PHP -> Servers. To define server configuration, click on the + button and set the name of the path mapping configuration. 



PHP/Servers settings dialog


 


In this example, I’m using¬†docker_symfony. I set the same name as the configuration and host names. By default, the port is set to¬†80. Change the debugger, if it is not automatically charged, to Xdebug. Below you will see the “Project files” mapping setting.¬† On the left side will be displayed the local path of the project files. On the right side, I need to set the path inside the Docker container.


You can find the path inside the docker-compose.yml file under the PHP service volume.



volumes:

     - '.:/app'


Save your changes. Now you are ready to start debugging. 



 Server path mapping configuration dialog



PHP Debug configuration interface


 


A short explanation of PhpStorm configuration interface options for debugging:



  • External connections

    1. Ignore external connections through unregistered server configurations

      • Suppose we set a custom server configuration name, as mentioned before. In that case, we can check this option to ignore other debugging requests from other projects open inside another instance of PhpStorm IDE.



    2. Break at the first line in PHP scripts

      • Helpful to test if the debugger is configured correctly. It will set the breakpoint on the first line in the index.php file.



    3. Max. simultaneous connections

      • Limits the number of debugging connections to IDE.





  • Xdebug



    1. Debug port

      • Sets the port, which will be used to listen to incoming debugging connection requests.



    2. Can accept the external connection

      • Enables/disables debug connection listener.






 



PHP / Debug configuration dialog


 


Step-by-step debugging


 


Setting breakpoints


To create a breakpoint, you have to click on the bar with the row numbers, and a red circle will appear. Clicking again on the same line number will remove the breakpoint.



Breakpoint example


To stop the program in the loop (for, while) or callback methods, we need to add a breakpoint inside them. Otherwise “step over” button will not enter into the loop/method.


Additional breakpoint options


 


Right-clicking on the breakpoint will give you additional options:



Breakpoint options


 


Using conditional breakpoints


 


To create a conditional breakpoint we need to add a condition that must be met to stop program execution on that breakpoint.



 


Debugging interface


 



 Debugging interface



 


Example:



IDE will follow the code by the execution priority. First, the getEmail method will be executed.



Second, the IDE will get to validateEmailDomain method after $login->getEmail() is executed.




On the left side of the debugging interface, you will see the list of scripts accessed during the program run. You can select each script and switch to each script code and see which was executed before the current breakpoint.



On the current break step, you can see active variables in the current script/class/method in the middle of the interface.



You will see the variables/code watchlist on the right side of the interface.¬† Press the¬†+¬†button to add a variable or code to execute or¬† to remove it from the watchlist.¬†When adding variables or code to the watchlist, you don’t need to add “;¬†at the end of the line.


Conclusion


I hope this has been a good introduction to how powerful¬†Xdebug is. It is a valuable tool and a huge time saver.¬†Xdebug can make your everyday development work much more¬†user-friendly and less mysterious.¬†I couldn’t imagine developing without it, and I hope you will also start using it in your work.


Give Kudos by sharing the post!

Share:

ABOUT AUTHOR

Tomislav Cipric

Tomislav is a senior software developer with 13+ years of experience in programming. He is specialized in Web application development technologies and project architecture design.