Updated:

## Install Xdebug

Setup Xdebug for improvements to PHP’s built-in debugging features and to allow IDEs to set breakpoints and step through scripts

If you are reading this, you must be very serious about making quality PHP web applications, and I commend you. You will be rewarded with several  installation steps, but these pertain to setting up the best debugging tool available for PHP.

### Linux

You will have the easiest time installing Xdebug through PECL, as all you need to run is pecl install xdebug. If you want the latest version available, you will have to get the source from xdebug.org.

### Windows

Grab the DLL for your PHP version from their site and make sure it is loaded with:

zend_extension = "C:\php\ext\php_xdebug.dll"

or wherever the file may be.

### OS X

Both Mr. Rethans and I recommend installing Xdebug through Homebrew:

# Find available Xdebug versions
brew search xdebug
# Use the package name of whichever version of PHP you have
brew install php71-xdebug

### Enabling the module

Of course, installation instructions for various platforms are provided.

Once you have the file(s), open your php.ini or xdebug.ini to add lines to let PHP know about Xdebug. At the very least, you’ll need a line such as above in the Windows section for including the extension file, whether it be a .dll or .so.

I would also recommend the following:

# This will enable the module
xdebug.remote_enable=1
# Set this to the host that the Xdebug client (your IDE, fancy text editor, etc.) is running on
xdebug.remote_host="localhost"
# The port that the client and server should listen on.
# The default is 9000 so you need not set this unless something else is already listening on that port.
xdebug.remote_port=9000

You can use a command like netstat to find out if port 9000 is available.

With the extension file and configuration in place, you should be ready to go. Restart Apache so we can make sure Xdebug is going. A quick way to see what modules PHP is running is to run the command-line interface with the -m option:

php -m

This will simply list all the active modules. You should see Xdebug in its own section at the bottom. To really see it in action, load up php-console and check the result of phpinfo(). You should now see a section talking about Xdebug:

php_info() showing Xdebug installed

var_dump an array to see the prettier view:

Xdebug and var_dump

And check out that improved error display! :

More colorful errors with Xdebug

## Debug PHP Scripts with Eclipse

The title says it all!

Now, all of your efforts will finally bear glorious fruit. You can use Eclipse to set breakpoints in a PHP script. To do so, you’ll need to make sure you have a PHP project open. Once that’s in order, click the triangle next to the Debug icon in the top bar and choose Debug Configurations…. Then, find the PHP Web Application section, right click it, and select New…:

Starting debug config screen

Here, we’ve renamed the Debug Configuration to Test Project. You can either edit the default PHP Server configuration, or create a new one. Let’s edit the Default one to something we’re more likely to commonly use.

Click Configure…, change Debugger to XDebug and the Base URL to the URL of your test site. In my case, I configured my web server and hosts file to make my site available at the specified address:

Edit the PHP Web Server

You should not have to make any other changes for a very basic setup.

Next, click the Debugger tab and change Server Debugger to XDebug. Click Configure… and make sure it’s using the right port. Again, be sure to confirm that the port it’s set to is not already being used by another program:

Some of the final settings for Xdebug in Eclipse

In the File box, choose a starting point from which to start the application (the document root):

Set the starting point (Document Root) of the web application

In this example, I’ll choose the only file in my test project.

Unclick Auto Generate in the URL section and make sure your file is named. I don’t really need to in my case since the file is index.php and the webserver will automatically serve that file when requesting the root of the site:

Web server starting point set

Next, I recommend setting Eclipse’s default web browser to the one you prefer using, rather than Eclipse’s built-in browser. Go to Window -> Preferences -> General -> Web Browser, click the radio button for Use external web browser, and then either select or add the browser you prefer using:

Select Eclipse’s default browser

When the debugger launches your project, it will do so in the selected browser.

Now, you should view your project in the Debug perspective so you can take advantage of the many tools here, especially those that let you set breakpoints and step through your script’s execution. Let’s say we wanted to pause the script at a certain point to see what was in a variable:

Pause at a breakpoint

This is an example of a script paused at a breakpoint. The browser is launched and only shows what data has been sent to the user at this point in the script. The top left Debug panel informs you that the script is paused at line 5. The upper right panels labeled Variables, Breakpoints, and Expressions are where you’ll probably spend the most time probing your script to see what happens when you run certain expressions. You can even directly manipulate the values of the listed variables so as to alter the web app’s operation once you continue execution, although sometimes variables may not be available for writing.

You have a significantly enhanced perspective of your web application with the debugger. If you mouse over any variable while the script is paused, you’ll actually see what’s in there at that point. What is most helpful is that when you Ctrl-click on identifiers, the IDE now has a much better idea of where code is coming from and the relationship between so many variables, so you’ll actually be led to where that identifier was defined more often than not.

### Miscellaneous Notes

If you enable autostart in the Xdebug config, then the Xdebug client will connect with the Xdebug server on every web server request . If it is turned off, they will only connect when a request parameter named XDEBUG_SESSION_START  or a cookie named XDEBUG_SESSION is sent with the request. You can set the value of the request parameter in the Debug Configurations for Xdebug.

Also note that sometimes Eclipse is set to break on the first line of every script by default. You will want to find this setting on the global level as well as the project level. Look in (Window) -> Preferences -> PHP -> Debug to see if Break at First Line is checked. Also look for this section in the Debugger tab of the project’s Debug Configurations.

## Debug PHP Scripts with PHPStorm

Debugging with PHPStorm is not all too difficult. It requires a similar amount of setup as Eclipse where you must define a site and debug configuration.

First of all, you should create a site configuration by either clicking the upside down triangle in the upper right of a new project and clicking “Edit configurations…”, or selecting this option in the Run menu:

Select Edit Configurations

From here, you should click the button with the three dots next to Server, where it currently says <no server> to create a new server:

Add a new PHP Web Application Server

On the next screen, provide a name for your server and a host name where it can be reached, as well as the server port. Xdebug should already be selected for Debugger. You should also let PHPStorm know where the root of the site is if it is not obvious. You may need to toy with these settings until you get things where PHPStorm is satisfied:

Setting up a test server

Also, click PHP Remote Debug in the left hand nav section to setup the debug server settings. When you click the three dot button here, you can choose the server you setup earlier. You can also choose an IDE key other than the default:

Enter the remote debug settings

You are finally ready to create a new PHP Web Application Server based on your Test Server. Click the Plus button in the upper left of the window and choose PHP Web Application Server. You can choose a name for this server and keep the configuration settings you created earlier:

Create a new Test Server app

Now is a good time to check the general PHP Debug options in Preferences -> Languages & Frameworks -> PHP -> Debug so you can set the right Debug port if it needs to be different from the default 9000, as well as other useful options:

Useful debug options

Go ahead and deselect Can accept external connections for Zend Debugger so that it does not try to run.

Next, it is a good idea to use PHPStorm’s excellent utility for validating your debug setup on the server. Go to Run -> Web Server Debug Validation and either fill in the fields for a Local or Remote Web Server. You should then correct any issues that it notes:

Validation the website

Note: I ended up setting xdebug.remote_host back to localhost because it was not able to find this machine with the testsite.local/localsite.local names set for it in /etc/hosts.

From here, you can set a breakpoint and either click Start Listening for PHP Debug Connections in either the Run menu or the icon in the upper right.

Now you can click Run -> Debug to launch the site with the Xdebug GET parameter to start debugging:

PHPStorm stopping at a breakpoint

## Tips and Tricks

If you are working with a web app that is so unfortunate as to make HTTP requests to itself in a way that you cannot pass the Xdebug request parameter, it might help to turn on xdebug.remote_autostart so that Xdebug is connecting on every request.

If several clients need to connect to the Xdebug server, such as several other developers on a single development server, you will need to turn on xdebug.remote_connect_back so that Xdebug will connect regardless of the hostname of the client.

If there are still issues, it might help to set xdebug.remote_log to an absolute path to a file to view the log output.

You can turn off all the fanciness of Xdebug’s error output when the following functions start your scripts:

xdebug_disable()
ini_set('html_errors', false);