Install XDebug And Configure Remote Debugging

at in tutorials

What Is XDebug

Debugging is the process of searching and resolving problems within applications and systems. And for this to be possible, you need visibility.

There are many ways to achieve that: you can track your app with external log files, you can spread “prints” and “exits” throughout your code, etc. But this is time-consuming, very error-prone, and can be impractical when the complexity of your codebase grows.

A better way to do this is to use XDebug extension. It is a debugging and profiling tool for PHP that comes with a lot of very cool functionalities, like drastically improving exception messages quality, exporting code coverage from your PHPUnit, and exporting profiling data for your KCahegrind.

But in this tutorial, we will focus on the remote debugging.

XDebug's (remote) debugger allows you to examine data structure, interactively walk through your and debug your code. The protocol that is being used is open, and is called DBGp.

1. Install XDebug Extension

APT

apt-get install -y php-xdebug

PECL

pecl install xdebug

With PECL you need to enable the extension in your php.ini, like this example, but please remember to modify the extension path to match your own.

zend_extension="/usr/local/php/modules/xdebug.so"

Mac OS

Even though it is available through Homebrew, a non-official package manager for OS X, Homebrew itself recommends using the PECL installation process.

For detailed information check the official installation guide

Remember to restart the PHP services needed before proceeding.

Verify The Installation

You can verify via the command line this:

php -i | grep xdebug

It asks PHP information (same information as provided by phpinfo function) and filters all lines that have XDebug in it.

If everything went well, you will see something like this:

/etc/php/7.2/cli/conf.d/20-xdebug.ini
xdebug
xdebug support => enabled
xdebug.auto_trace => Off => Off
xdebug.cli_color => 0 => 0
xdebug.collect_assignments => Off => Off
xdebug.collect_includes => On => On
xdebug.collect_params => 0 => 0
xdebug.collect_return => Off => Off
xdebug.collect_vars => Off => Off
xdebug.coverage_enable => On => On
xdebug.default_enable => On => On
xdebug.dump.COOKIE => no value => no value
xdebug.dump.ENV => no value => no value
xdebug.dump.FILES => no value => no value
xdebug.dump.GET => no value => no value
xdebug.dump.POST => no value => no value
xdebug.dump.REQUEST => no value => no value
xdebug.dump.SERVER => no value => no value
xdebug.dump.SESSION => no value => no value
xdebug.dump_globals => On => On
xdebug.dump_once => On => On
xdebug.dump_undefined => Off => Off
xdebug.extended_info => On => On
xdebug.file_link_format => no value => no value
xdebug.filename_format => no value => no value
xdebug.force_display_errors => Off => Off
xdebug.force_error_reporting => 0 => 0
xdebug.gc_stats_enable => Off => Off
xdebug.gc_stats_output_dir => /tmp => /tmp
xdebug.gc_stats_output_name => gcstats.%p => gcstats.%p
xdebug.halt_level => 0 => 0
xdebug.idekey => no value => no value
xdebug.max_nesting_level => 256 => 256
xdebug.max_stack_frames => -1 => -1
xdebug.overload_var_dump => 2 => 2
xdebug.profiler_aggregate => Off => Off
xdebug.profiler_append => Off => Off
xdebug.profiler_enable => Off => Off
xdebug.profiler_enable_trigger => Off => Off
xdebug.profiler_enable_trigger_value => no value => no value
xdebug.profiler_output_dir => /tmp => /tmp
xdebug.profiler_output_name => cachegrind.out.%p => cachegrind.out.%p
xdebug.remote_addr_header => no value => no value
xdebug.remote_autostart => Off => Off
xdebug.remote_connect_back => Off => Off
xdebug.remote_cookie_expire_time => 3600 => 3600
xdebug.remote_enable => Off => Off
xdebug.remote_handler => dbgp => dbgp
xdebug.remote_host => localhost => localhost
xdebug.remote_log => no value => no value
xdebug.remote_mode => req => req
xdebug.remote_port => 9000 => 9000
xdebug.remote_timeout => 200 => 200
xdebug.scream => Off => Off
xdebug.show_error_trace => Off => Off
xdebug.show_exception_trace => Off => Off
xdebug.show_local_vars => Off => Off
xdebug.show_mem_delta => Off => Off
xdebug.trace_enable_trigger => Off => Off
xdebug.trace_enable_trigger_value => no value => no value
xdebug.trace_format => 0 => 0
xdebug.trace_options => 0 => 0
xdebug.trace_output_dir => /tmp => /tmp
xdebug.trace_output_name => trace.%c => trace.%c
xdebug.var_display_max_children => 128 => 128
xdebug.var_display_max_data => 512 => 512
xdebug.var_display_max_depth => 3 => 3

Or if you have installed PHP as a module in Apache you need to use the phpinfo function in a test page to check.

2. Configure

One thing that surely creates a lot of confusion is how this feature works.

The debugger, in this case, probably your IDE, is the server, and XDebug the client, so that’s why you need to point out the remote_host and choose the port. To inform to where your client should send its information.

Due to Mac OS X limitations, you will need a static IP for your remote host different from 127.0.0.1, so to keep it consistent between OSs I use the same approach in both Mac OS and Linux.

Example of how to add a static IP to your localhost in MAC OS, please note that your network interface might be different:

sudo ifconfig lo0 alias 10.254.254.254

And this are the instructions to be added in your php.ini.

[xdebug]
#enable the remote debugging feature
xdebug.remote_enable=on
xdebug.remote_autostart=on
#which port should XDebug send the information
xdebug.remote_port=9000
#remote ip, replace this with your IP
xdebug.remote_host=10.254.254.254
# keep this if you are having trouble and need to figure out why
xdebug.remote_log="/tmp/xdebug.log"

Conclusion

Now you have installed XDebug extension, enabled and configured the remote debugging feature.

Next, we will see how to set up Neovim as a debugger client for PHP projects.

:D