creativity

print_r, or: How I Learned to Love Debugging PHP

To someone who hasn't had some success at programming, the process of writing code must seem like a long struggle with a math problem. Luckily, it's not quite like that. It's true that programming depends on basic logic and mathematical concepts. Also, it involves a problem to be solved. However, the motivation to undertake most programming projects is to be able to do something novel and unique, so the problem-solving process at a project level involves imagination and does not end with an answer that simply could have been looked up.

Within the process of developing a program, there are several repetitions of the process of writing code and testing its effectiveness. This is perhaps the strongest manifestation of the scientific method in programming. Beginning with a hypothesis of how something should work, one proceeds to test it, seeking to dis-confirm it, and adapting the initial hypothesis when a problem is revealed. This process occurs in iterations from the beginning to the end of development.

A productive programming approach depends not only on writing code but also significantly on this process of scrutiny and testing. Debugging is a name given to this process of finding reasons why something doesn't work or why your assumptions about how something works are mistaken.

In the spirit of a more satisfying coding experience, I'm sharing a few methods and tools that I have adopted to be more efficient in debugging PHP. PHP offers some unique challenges for the process of debugging: PHP has no internal debugger and no native development environment, so it is not immediately apparent how to do things like watching the code run line-by-line and accessing the variable states. Additionally PHP-based web applications need to be tested as they are used — through the interaction of a web browser and server — so, the interpreter is independent of the developer's environment. All of this means that debugging PHP usually involves analyzing the output of the program and trying to deduce from that how the code works or fails.

Use var_dump to investigate variables

A frequent question in debugging a program is what the value of a variable is in a given state. Without being able to stop the program's execution at that state and see the variable's value, one needs to output the variable to the screen (in a web browser or at the console) or write it to a file to check later.

The most well-known ways to write the value of a variable in PHP are the echo and print statements. These work as expected for strings and numbers, but are ambiguous if the variable is TRUE, FALSE, or NULL, and don't show the contents of arrays or objects. These shortcomings make echo and print highly problematic for effective debugging, because by giving ambiguous results they prevent you from disconfirming relevant possibilities.

Enter: print_r, var_dump, and var_export. These three functions output variables in forms much more suitable for debugging. The functions print_r and var_export also allow you to have the output returned as a string (instead of written to the standard output -- typically the console or web browser) which makes them useful if you want to send the data to a log or do something else with it.

This is an illustration of the different results given by the different output functions for different data types:

Value / Statement echo print print_r var_dump var_export
0 0 0 0 int(0) 0
NULL [empty] [empty] [empty] NULL NULL
FALSE [empty] [empty] [empty] bool(false) false
TRUE 1 1 1 bool(true) true
Array() Array Array Array ( ) array(0) { } array ( )
StdClass() [error] [error] stdClass Object ( ) object(stdClass)#1 (0) { } stdClass::__set_state(array( ))

Notice that var_dump is the only function that provides output that fully distinguishes the different data types.

Use debug_backtrace to find where you are

Another frequent question is how the program got to a particular section of code. Maybe you know that a specific part of a program is failing, but if it is used in many parts of the program, you may not know what condition leads to the failure. You can use PHP's debug_print_backtrace to get a list of the functions that the program travelled through. This includes the names of the functions and their arguments.

Get used to the PHP language reference

The PHP Manual is probably the best resource for checking the syntax of functions and control structures, learning the definitions of data types, as well as getting additional commentary and suggestions from users.

It is also pleasantly easy to quickly look things up. For most functions, you can use:
http://php.net/[function_name]

For example:
http://php.net/var_dump

Many data types can be accessed using a similar method. For example, the reference on the string data type is:
http://php.net/string

Alternatively there is a page with all of the string-related functions at:
http://php.net/strings

Also all of the operators at:
http://php.net/operators

And an easy link to a page on if/else if/else, which is within a click of the other control structures:
http://php.net/if

Give yourself the advantage of some extra tools

When I started programming, I preferred using a very simple text editor for writing code. However, as the projects that I worked on grew, I migrated to using Eclipse with PHP Development Tools (PDT). Now I consider many of the features to be indispensable, including code completion, syntax checking and coloring, and integration with version control systems.

Although PHP does not have an internal debugger, there are third-party extensions available that add powerful debugging and profiling features to the PHP engine. I use the free and open-source Xdebug, which works with Eclipse to allow you to watch the code execute line-by-line, assign break-points, and access the values of variables within the current state of execution.

When developing a web application where the product is a website, it is essential to set up a development site that simulates the production site. The goal is to have an accurate simulation or mirror of the production environment, while maintaining flexibility to experiment and be able to revert changes to a previous version. One approach for setting up a development mirror is to create a copy of the site on the same or a similar server. Another approach is to run server software on your computer (like by using an AMP software package) or running a Linux host (with Apache/MySQL/PHP) through virtualization software. I use VMWare's Fusion software (commercial license) to virtualize a Linux host as needed on my Mac. Sun's open-source VirtualBox software has been under rapid development for the last year and is worth considering.

Finally, the Charles web debugging proxy is invaluable for debugging the complex stream of communication in web applications between client and server. When enabled, Charles records the complete set of transactions through a web browser (including those initiated by embedded Flash applications and AJAX requests) and offers useful tools for displaying various types of content (including XML, JSON, AMF-encoded, and binary data).

Conclusion

These techniques and approaches to debugging PHP are among the most useful lessons I've learned while working with PHP. The process of debugging has significance beyond testing whether a particular piece of code works. It is an essential part of the self-learning that takes place when working with a programming language. This self-learning is the result of a problem-solving methodology that begins with a unique question of how to accomplish something and applies techniques in dialogue with the program until a result is revealed.

Syndicate content