Introducing xdebug

December 10, 2007

Tutorials

Introducing xdebug

By: Stefan Priebsch

Other Articles in the Series

Part One: Introducing xdebug
Part Two: Tracing PHP Applications with xdebug
Part Three: Profiling PHP Applications With xdebug
Part Four: Debugging PHP applications with xdebug
Part Five: Creating Code Coverage Statistics with xdebug

This article is the first installment of a five-part series of articles covering xdebug, a free and open source
swiss army knife tool for PHP developers.
xdebug is a PHP extension created by Derick Rethans, one of the PHP core developers. This week, we will show you how to install xdebug and introduce you to some of the basic features.
In the subsequent parts of this article series, we will have a closer look at one of xdebug’s main features,
namely tracing, profiling, debugging, and code coverage.

Installing the xdebug extension

First of all, we need to install xdebug. As I write this article, the current version is 2.0.1.
Since the internal PHP APIs may change between different PHP releases, you must make sure
that the version of xdebug you are installing matches the PHP version you are using.

xdebug does not work with any PHP versions before 4.3, and will probably not yet work with PHP 6.
This is not a real problem, however, since PHP 4 will reach its end of life in 2008,
and PHP 6 will probably not be available before the end of 2008. This gives you enough
time to get used to xdebug so you can use it as a helpful tool when it comes to migrating your PHP code
to work with the next major or minor PHP release.

Installing on Unix

Before we dig into xdebug’s features, let us get the installation done.
On Unix, you can try installing xdebug through PECL, the PHP extension community library.
The PECL installation does not work on all systems, though. If the PECL installation does not
work out for you, you must compile xdebug from source. But first, try the PECL installation:

pecl install xdebug

If the PECL installation does not work for you, you need to compile xdebug from source.
In addition to a C compiler, you will need appropriate versions of the
usual build tools (Autoconf, Automake and Libtool). If they are not already installed
on your system, you can usually install them by running apt-get install build-essential
on Ubuntu or Debian.
When configuring xdebug, you will get an error when any required tool is missing. In this case,
just install the missing tool, then configure xdebug again.

Furthermore, two helper programs, phpize and php-config that are a part of PHP, are required.
If you have not compiled PHP from source, you will probably have to install
the developer packages using your distribution’s package manager.
On Ubuntu or Debian, you can install the PHP development tools using a command like
apt-get install php5-dev.

Please note that phpize and php-config must match the PHP version you are using,
so do not just copy them to your system from some other PHP installation. When your development tools are in place, you can download and compile xdebug:

wget http://xdebug.org/link.php?url=xdebug201
tar -xzf xdebug-2.0.1.tgz
cd xdebug-2.0.1
phpize
./configure --enable-xdebug --with-php-config=/usr/bin/php-config
make
cp modules/xdebug.so /usr/lib/apache2/modules/xdebug.so

The php-config path may be different on your system,
and depending on the your Apache installation directory,
you may need to copy xdebug.so to another directory.
Instead of copying the file, you can of course create a link as well.

Installing on Windows

If you are a Windows user, you can download a compiled DLL from xdebug.org.
Select the PHP version you are using and click the appropriate link in the Windows modules section in the right column of the page.

You must use the non-debug version of PHP with xdebug. If you have downloaded PHP from php.net,
debugging should not be enabled. When in doubt, check the Debug Build entry in the phpinfo() output.

I would recommend putting the downloaded DLL into PHP’s extension directory ext, which should be a subdirectory of your PHP directory. You can put the DLL to any directory, provided that you state the full path to the DLL in php.ini.

Activating the xdebug extension

Now you have the xdebug extension ready, either as a shared object on Unix or a DLL on Windows.
To activate xdebug, you must add an entry to php.ini. On Windows, use:

zend_extension_ts="c:\php\ext\php_xdebug-2.0.1-5.2.1.dll"

On Unix, use:

zend_extension="/usr/lib/apache2/modules/xdebug.so"

instead. The path to PHP’s extension directory or Apache’s module directory may differ on your system. Make
sure you specify the full absolute path, not a relative path.

Please note that on Windows, we use zend_extension_ts, which means that a
thread-safe extension is loaded, whereas on Unix, we a non-threadsafe extension is loaded.
Depending on your system setup,
you must decide for yourself wether you need a thread safe or non-thread-safe extension.
If you are not sure wether your PHP installation is thread-safe,
check the Thread Safety entry in the phpinfo() output.

You should not load any other Zend extensions while working with xdebug,
because they would probably use the same internal mechanisms in the Zend engine,
which usually calls for trouble. Not all Zend extensions work together with xdebug.
Since you will probably use xdebug on a development system rather than a live system, this is
no serious limitation. The most important rule is to not mix xdebug with other PHP debugger extensions.

Having restarted your web server because we changed php.ini, you can check
the output of phpinfo() or run php -m at the command line.
In each case, xdebug must be listed twice, once as a PHP extension, and as a Zend extension as well.

Take care when you are updating PHP with xdebug installed. If the internal APIs change between the PHP
versions (which does not happen on every new version, but will certainly happen when you are close to a project deadline), the new version of PHP will probably not start or at least give you funny errors.
If need be, you can always get away with disabling xdebug, at least temporarily, to get an updated
PHP version to work and re-enable xdebug as soon as a new version is released that works with the newer API version.

There are quite some php.ini switches to configure xdebug,
but most of them have sensible deafult values,
so we can start using xdebug without worrying about configuration settings right now.
We will take a look at the most important configuration settings as we need to.

Improved var_dump() output

Let’s face it: the most widely used PHP debugger is var_dump().
Given the dynamic nature of PHP, and the fact that PHP is a scripting language, there is nothing wrong
in using var_dump() – I do it all the time. The drawback is that you have to modify your
program to debug it. The more var_dump() statements you put into your code, the more likely
it is that you’ll forget to remove them all once you have found and fixed your bug.

xdebug offers interesting alternatives to the extensive use of var_dump() statements
for debugging your code, which we will get to know in the next and last article of this series. But for now,
you’ll be glad to hear that xdebug even improves our beloved var_dump() debugger.

When the xdebug extension is loaded, the output of PHP’s var_dump() function is automatically
beautified for better readability, as the following screenshot shows:

You can configure the way xdebug formats the var_dump() output by various php.ini settings.
First of all, you can change the length of strings that xdebug displays. The default
value is 512; longer strings are automatcally truncated.

Wether you want xdebug to display the full string depends on the situation, and the size of data you work with. If you work with big strings, the var_dump() output can get long and hard to read, thus is is a good idea truncate strings for better overview. On the contrary, if you are looking for a specific value in the output, you will probably want the strings to be displayed in full length.

To change the string length xdebug displays, add

xdebug.var_display_max_data=<your preferred value>

to php.ini and restart your web server so that this setting takes effect.
Alternatively, just like you can change various php.ini settings of the PHP core at script
runtime by ini_set, you can add


ini_set('xdebug.var_display_max_data', <your preferred value>);

on top of your script to make sure the ini_set-command is executed before your first var_dump() is encountered, otherwise your runtime setting will not take effect.
Configuring xdebug at runtime with ini_set saves you from restarting your web server every time you want to modify the xdebug configuration and makes you much more flexible.

You can also control the number of array elements or object properties that xdebug displays. This is done by modifying the xdebug.var_display_max_children setting, which defaults to 128. This value should be sufficient to display all properties of your objects, but if you work with large arrays, you might still need to increase this value.

If you work with nested objects and arrays, you may want to modify the xdebug.var_display_max_depth setting. This setting has a default value of 3, which means that three nested levels of array elements and object relations are displayed.

You can also dump the values of the superglobal variables using the xdebug function xdebug_dump_superglobals(). As the superglobals, especially $_SERVER,
are arrays that contain many values, you must explicitly tell xdebug which array keys you would like to see.
To do this, set xdebug.dump.<superglobal name> where <superglobal name> is one of
GET, POST, SERVER, COOKIE,
FILES, REQUEST, or SESSION.
Use the array key(s) that you want xdebug to display as argument, using a comma-separated list if you
want to display more than one key per superglobal variable. You can use * as a wildcard
to display all keys, which can be useful for $_GET and $_POST.

Using

ini_set('xdebug.dump.SERVER', 'HTTP_HOST, SERVER_NAME');

in your PHP script or setting

xdebug.dump.SERVER=HTTP_HOST, SERVER_NAME

in php.ini will display the value of $_SERVER['HTTP_HOST'] and $_SERVER['SERVER_NAME']. To display all GET parameters that were passed to the script, use

xdebug.dump.GET=*

By default, xdebug does not dump undefined values, but just skips the respective array keys.
To force display of undefined values, set xdebug.dump_undefined to On. I would
recomment turning xdebug.dump_undefined on, because it can be quite confusing if you.

You may wonder why xdebug supports configuring displaying select items of superglobal variables, when the
same effect could be achieved with a number of var_dump() statements.
First of all, you can have values of different superglobals displayed in one spot in a very readable way.
Second, and more imporant, xdebug does not only show these superglobals when you call
xdebug_dump_superglobals(), but also when any error occurs in your script, as
we will see in the next section.

Better error messages

xdebug also improves the way PHP displays error messages by automatically displaying a stack trace along with
every PHP error message, warning and notice.
This stack trace lists the history of function calls that lead to
an error. As PHP programs become more and more object-oriented,
sometimes errors tend to show up deep inside libraries or helper
objects. The stack trace allows you to quickly find out where the
code piece that caused an error was originally called from.

Since version 5.0, PHP also has a native function debug_print_backtrace()
that displays the stack trace, but you’d have to call this function explicitly each time
an error occurs, which means that you would have to create a custom error handler just
to display stack traces along with error messages. Also, the stack trace created by
xdebug is easier to read than the output of the native PHP function.

Like PHP itself, xdebug only displays error messages when display_erorrs is set to On in php.ini. On a development system, this should be the case. If not, add


ini_set('display_errors', 'Off');

to your script to change the setting at runtime.

Looking at this stack trace, you can see that the function foo() was called, which
called bar(), which in turn called baz(). In addition to the name of the calling
functions and where they are located in the source code, xdebug displays a timestamp and the amount of
memory used by the script when the function was called.

In the previous section, we have already learned how to configure xdebug to display values of superglobal variables.
In addition, you can configure xdebug to display the current values of local variables as well.
To display local variables along with every error message, you need to add


xdebug.show_local_vars=1

to php.ini. You can use ini_set as well, which we won’t repeat mentioning from now on.
Just keep in mind that you can do a lot of configuration at runtime, but you can obviously not
change settings that affect work that is done before your script actually starts.

By the way, the php.ini settings xdebug.var_display_max_data, debug.var_display_max_children, and xdebug.var_display_max_depth that we used above to control the formatting of the var_dump() output also affect the format of variables that xdebug outputs in error messages. The same holds true for display of superglobals.

There is even more. With xdebug.collect_params, you can configure xdebug to display information about the parameters that were passed to a function. xdebug.collect_params takes a numeric parameter, with 0 meaning no additional information, and 4 meaning to display the variable name and always the full contents of each function parameter. A value of 3 will display name and parameter, but honoring the configuration settings mentioned above and thus truncating long variable content. A value of 1 will display the type and number of elements only, whereas 2 will in addition display the full information in a tooltip. Using a tooltip is very convenient for online viewing, but not really suitable for printing the information.

Here is the xdebug configuration used to create the following screenshot:

xdebug.show_local_vars=On
xdebug.dump.SERVER=HTTP_HOST, SERVER_NAME
xdebug.dump_globals=On
xdebug.collect_params=4

This screenshot was taken using the following xdebug configuration:

Please note that the more information you ask xdebug to collect during script execution, the more memory and computing time it will use, thus slowing the execution of your script. Make sure to only enable xdebug on development systems, and never on production systems. It is not a wise idea to display error messages as part of the HTML result on production systems, and it is even less of a good idea to enrich this information with stack traces and potentially variable values. Imagine your web site displaying your database username and password to everybody just because you use an uninitialized variable!

Since superglobal variables should not change at runtime,
xdebug by default displays them only on the first error message, not in every error message.
If you want xdebug to repeat dumping the global variables on every error, use

xdebug.dump_once=Off

Please note that the extended error
display of xdebug does not work if you define a custom error handler
using register_error_handler(). This is because xdebug
internally uses the same mechanism. Should your scripts use a custom
error handler, you can still use the function
xdebug_get_function_stack()
to output the stack trace in your custom error handler.

Object-oriented code uses exceptions when something goes wrong. Since an exception is not an error,
xdebug will not display a stack trace when an exception is thrown, but only if that exception is uncaught.
That is because an uncaught exception is a fatal error.
To can configure xdebug to display a stack trace whenever an execption is thrown, use


xdebug.show_exception_trace=On

Recursion Limit

Another very useful feature is the fact that xdebug limits recursion depth,
thus preventing endless recursion, which usually makes PHP segfault on Unix.
On Windows, PHP even locks up the whole system when it falls into endless recursion, which
is usually far worse than having PHP segfault.

xdebug prevents endless recursion by stopping the script once a pre-defined nesting depth is reached.
This is, in effect, a limit of the stack size. Every recursive function call will increase the stack size,
but also nested regular function calls increase the stack size.
The default value is 100 and this feature is enabled by default.
You can modify this limit, which might be necessary if you
work with a script that works on deeply nested recursive data structures.


xdebug.max_nesting_level=<your preferred value>

Bear in mind, however, that xdebug does not prevent endless loops with for, while or similar, since they do not increase the stack size. You can easily put an additional counter into such loops, however, that just kills the script after a ridiculously high number of repetitions. I would not recommend doing this in production code, though, since a program can can never tell wether a loop is endless.

Conclusion

xdebug is a small, but very useful tool in PHP development.
It should be installed and activated on every PHP installation that is used for development.
You should not run xdebug on a production system, though, because most features degrade
performance. Personally, I would never want to miss xdebug a single day on my development system,
and if it is just for the better formatting of the var_dump() output.

Today, we have just scratched the surface of what xdebug
can do to make your every day’s life as a developer much easier.
Next week, we will explore the tracing features of xdebug.
Tracing helps you better understand your applications, and can be a replacement
for putting loads of var_dump() statements into your code.

Make sure you check back here next week for the second part of this series of xdebug articles.
Until then: Happy coding – with xdebug enabled.

About the author:

Stefan Priebsch has been solving IT problems for over 25 years.
He is founder and CEO of e-novative GmbH, one of the first German IT
consultancies offering PHP-based solutions.
Stefan holds a university degree in computer science,
is an internationally recognized PHP expert, book author, trainer and consultant.
You can reach him at stefan.priebsch@e-novative.de.

About Cal Evans

Many moons ago, at the tender age of 14, Cal touched his first computer. (We're using the term "computer" loosely here, it was a TRS-80 Model 1) Since then his life has never been the same. He graduated from TRS-80s to Commodores and eventually to IBM PC's. For the past 10 years Cal has worked with PHP and MySQL on Linux OSX, and when necessary, Windows. He has built on a variety of projects ranging in size from simple web pages to multi-million dollar web applications. When not banging his head on his monitor, attempting a blood sacrifice to get a particular piece of code working, he enjoys building and managing development teams using his widely imitated but never patented management style of "management by wandering around". Cal is currently based in Nashville, TN and is gainfully unemployed as the Chief Marketing Officer of Blue Parabola, LLC. Cal is happily married to wife 1.28, the lovely and talented Kathy. Together they have 2 kids who were both bright enough not to pursue a career in IT. Cal blogs at http://blog.calevans.com and is the founder and host of Day Camp 4 Developers

View all posts by Cal Evans

16 Responses to “Introducing xdebug”

  1. g2ktcf Says:

    After PHP 5.3, you no longer use the _ts……!! Its all working now!

  2. g2ktcf Says:

    I too am having trouble with the _ts…the only way I can get this to show up under phpinfo is to use zend_extension = "C:\xampp\php\ext\php_xdebug-2.1.1-5.3-vc6.dll". However, I have not been able to get XDebug working yet.

  3. vainshane Says:

    The instructions are correct, but somehow this took me forever to figure out how to install on windows with PHP 5.3

    First, fire up phpinfo() and have a look for lines like these:

    Compiler MSVC6 (Visual C++ 6.0)
    Thread Safety enabled

    These correspond to the "VC6"/"VC9" and "NTS" on the download page. If thread safety is enabled (I suppose this would usually be the case on windows) you want the package which does not say "NTS" (short for Non Thread Safe).

    And of course you have to match your PHP version.

    Lastly, even if you’re running a 64 bit version of Windows, PHP is likely to be running in 32 bit mode, so don’t use the 64 bit version of XDebug unless you’re sure you need it.

    Once you’ve got the right DLL, put it in your /ext directory and add the line:

    zend_extension=C:\wamp\bin\php\php5.3.0\ext\php_xdebug-2.0.5-5.3-vc6.dll

    No quotes worked for me, but the install page does mention that sometimes you need them — maybe for when there are spaces in the path.

    Note also that it’s "zend_extension", not "zend_extension_ts" as in previous versions.

  4. repdetec Says:

    First of all, none of the windows builds work with 5.3.

    I reinstalled Zend Server CE to get php 5.2 on my system. I downloaded the XDebug dll for it. My php.ini looks like this:
    zend_extension_ts="C:\Zend\ZendServer\lib\php_xdebug-2.0.1-5.2.1.dll"
    zend_extension="C:\Zend\ZendServer\lib\ZendExtensionManager.dll"
    However, when I restart the webserver, XDebug still does not show up under phpinfo(). Any ideas?

  5. productive Says:

    Im struggling trying to install the xdebug module.

    It is IIS7, php 5.2.6, fastcgi version.

    Ive put the dll in c:\php\ext and added this line to the php.ini file :

    zend_extension="c:\php\ext\php_xdebug-2.0.3-5.2.5.dll"

    The php installation isnt thread safe so no _ts

    But after restarting IIS nothing has changed, there is no mention of xdebug in the phpinfo() output, does anyone know what might be wrong?

  6. theloginn Says:

    It might be nice to point out that appart from display_errors=on you also need html_error=on to get the nice orange error dumps.

    As it took me a half hour to figger out,….

  7. e-novative Says:

    To awjrichards: it’s not an error, but I should have made the sentence clearer: I’m saying that you should turn error display ON for development systems, and OFF for development systems, that’s what the code example refers to.

    I feel it is more secure to turn off error display explicitly in your code, since this makes the code independent from php.ini.

  8. awjrichards Says:

    Thanks for the great article!

    There is, however, an error that I stumbled across. In order for xdebug to display errors, you must have display_errors set to on in php.ini. You provide a snippet of code to use ini_set() to turn this on, however the code you provide actually turns it off…
    Thus,
    ini_set(‘display_errors’, ‘Off’);

    should be:
    ini_set(‘display_errors’,'On’);

  9. e-novative Says:

    Hi everybody,

    thanks for your feedback to my article. It took me a few days to realize that the article had been published [hint, Cal! ;-)]

    True, xdebug is not compatible with Zend debugger. Both would try to modify the same Zend Engine internals, which obviously does not work. You have to choose either, but it’s rather easy to switch between the different extensions, so you can use whichever better suits your current needs.

    We will cover debugging with xdebug (together with Eclipse PDT) in the fith part of the series, so please stay with me. I’ll be back ;-)

    Chuck, if you specify a full path, the xdebug extension should load just fine. If not you might want to load xdebug as a non-threadsafe extension (zend_extension=…) – but on my system thread-safe loading works fine at the command line. Let me know how it works out for you.

  10. _____anonymous_____ Says:

    To Chuck Burgess – nothing happened for me at first either. Then I realised it doesn’t respect the extension_dir setting in php.ini, so you *must* provide the full path to the DLL. When I did that it worked straight away. Maybe that’ll work for you too.

  11. vorozhko Says:

    1.XDebug is not compatibility with ZendDebugger
    2.Instead of XDebug i can Run ZendDebugger to see my code line by line – can you explain me how to do the same in Xdebug.
    3.Xdebug not compatibility with ZDE, i don’t want to use Eclipse but Zend Neon is still beta.

  12. acrossley Says:

    PHP Fatal error: [Zend Optimizer] Zend Optimizer 3.3.1 is incompatible with Xdebug 2.0.2-dev in Unknown on line 0

    I am saddened. Is there anything I can do? or is it just that way?

  13. _____anonymous_____ Says:

    thorie79: I was hoping that was the case, but today makes the third attempt I’ve installed xdebug, configured it to where I see it in "php -i", but see no indication of it when I run a simple test of using var_dump().

    Other than adding the zend_extention_ts line in php.ini, what else do you have to do? Is there something you need to add at the start of a php file?

  14. thorie79 Says:

    I do it all the time when I run unit tests for my php applications. If you get funky output (like html tags around the xdebug error messages), b sure you have compiled php for CLI instead of CGI.

  15. _____anonymous_____ Says:

    Following your instructions, I don’t see any actual effect when I’m using PHP at the command line. Is xdebug only usable in conjunction with a web server like Apache? I only run PHP at the command line as a scripting language, not as a web platform, and therefore I have no web server installed or running. Does this mean I cannot use xdebug?

  16. max1986 Says:

    xdebug looks very nice for me. I never heard of it. So I will try it. The different output from a var_dump is a nice feature :).

    Keep up the good work and I will follow the nice articles of you :)