PHP Tutorial :: Debugging

PHP Example #112

Controlling where errors are displayed

Programs with a certain level of complexity rarely work at the first try, and some errors can be tricky to detect. The first step to fix an error is to read its description and see in which line it was detected (which is not always where the error really is). To have the error messages displayed in the browser, we have to set on the configuration directive display_errors; if we set on log_errors as well, the error messages will be saved in the server's error log file.

Which kind of errors can we have in a PHP program? A typical one is the syntax error, which of course stops the execution of the program. PHP can be considered as a language that has a complex syntax, that relies a lot in symbolic characters and signs such as quotes, commas, semicolons or brackets. It is very easy to omit or mistype any of these, so when facing this kind of errors, the first approach should be to watch these elements, firstly in the line where the errors are detected, and then in previous lines if needed be.

There are also the so called fatal errors, which happen for example when the program calls for functions that doesn't exist. As expected, the program will terminate its execution and we will have to check the presence or absence of functions or files that are required to run the program.

Warnings and notices are errors that do not terminate the execution of the program, and can be optionally ignored by the programmer, albeit it is not the ideal practice. These errors are commonly caused for calling a function with an erroneous number of arguments or printing a variable that has not been initialized. The programmers that don't want to bother with these lesser errors can deactivate the notifications via the configuration directive error_reporting. The source codes in these tutorials have been written to be clean of warnings and notices, since in this server every kind of error is set to be displayed.

PHP Example #113

Checking syntax errors

The PHP interpreter is quite cryptic when notifying errors and this may be rather frustrating for the less experienced programmers. To prevent the most frequent serious errors, the syntax errors, it is highly recommended to write PHP in a good editor that recognizes PHP programming and not in any cheap Notepad clon. It is very important that the editor indicates the number of line and shows in different colors the various elements on the source code, to facilitate the checking when errors are found. These characteristics are commonly (if not always) found in modern HTML editors, for the case that the programmer does not bother to use a special PHP editor with more advanced features.

Syntax errors are verifiable by looking firstly at the line where they are reported to be. If the line doesn't has any error, then we have to check previous lines until the cause of error is found. These errors are caused most of times by any kind of delimiters: quotes that delimite strings, parentheses in function calls and checking expressions, or brackets in array elements and code blocks. Always make sure that these elements have their closing or opening counterparts. Another source of problems are the semicolons that have to be written after each statement, perhaps the most sterile characteristic inherited from the C-ish languages. Why do I have to write a sign on every finished line instead of only in the lines that I want to break or join, which are, of course, a small minority, since breaking lines is rarely used, while joining lines is, besides that, not a good practice from the viewpoint of readability.

So in the little piece of code below, we can see a typical syntax error: the string "David" has been opened with a double quote but closed with a single one. This makes the PHP interpreter to "think" that the string instead of being "David" is "David'; if ($logged_in) { print " and after that what "he" finds is the word Welcome, instead of a recognizable command. Therefore, we have an error in the line 2 that will be reported as an error in the line 4... With PHP, this is the bread of everyday.

$first_name = "David';
if ($logged_in) {
print "Welcome, $first_name";
} else {
print "Howdy, stranger.";

PHP Example #114

Inspecting data

After removing all the syntax errors, we should have a well-working program, but this is often not true. One of the most devious enemies of the programmer are the logical errors, those that the interpreter can't detect, and are errors just because they work against our logical thinking. For example, if we have to make a program that calculates the total amount of a meal in a restaurant, we can mistype an arithmetic sign, so for example, instead of adding the price of the drink, the program would subtract it because the programmer made a typographic mistake that went unnoticed. Of course, the PHP interpreter doesn't care about that, since for "him" adding and subtracting are valid the same, but for whoever is going to charge the bill, it really matters.

When we find this kind of errors, it will not be usually in such a simple program, and the headaches sometimes get notorious. To find the source of the error, we have to analyze the content of the variables, and find which one or ones do not have the values that should have, and ultimately, why they don't. The simplest way is to use a print or echo statement to explicitly display on screen the value of a certain variable in a certain moment on the execution of the program. This method is effective, but when we have an array with several (or many) elements, it is not nice; in such case, we would have to use the function var_dump() as shown in the example, where it displays on screen the values of our beloved array $_POST[] with a correct format, courtesy of the HTML element <pre></pre>'.

A typical confusion when debugging PHP programs is caused when we retest the program after fixing the errors and we see no change in the behaviour of the program. This is just caused by some distraction, like for example, when we modify our files in our local computer and test them in our remote server, forgetting to upload the modified files to the server (a typical miss caused by the impatience).

print '<pre>';
print '</pre>';

PHP Example #115

Inspecting data

Displaying debug messages mixed with the habitual output of the program can generate confusion in some cases. A way to avoid this is to redirect the debug messages to the server's error log file, by using the function error_log(), as we can see in this example, where error_log() is used instead of print or echo.

$prices = array(5.95, 3.00, 12.50);
$total_price = 0;
$tax_rate = 1.08; // 8% tax
foreach ($prices as $price) {
error_log("[before: $total_price]");
$total_price = $price * $tax_rate;
error_log("[after: $total_price]");
printf ('Total price (with tax): $%.2f', $total_price);

PHP Example #116

Inspecting data

Sending debug messages exclusively to the server's error log file gets more complex when using var_dump(), because we have to prevent var_dump() from printing the information on screen. The way to do this is by surrounding var_dump() with functions that temporally stop the printing of any result during the execution. By using the functions ob_start(), ob_get_contents() and ob_end_clean() we send the results of var_dump() to an internal buffer instead of printing them.

// Captures the result instead of printing it
// Calls var_dump()
// Stores in $output the result generated by var_dump()
$output = ob_get_contents();
// Returns to the habitual way of printing the result
// Sends $output to error log file