PHP Debugging Basics
by David Sklar, author of Learning PHP 508/12/2004
Whether you're a PHP newbie or a wizard, your programs are going to have bugs in them. Nobody's perfect. This article gives you some techniques for finding and fixing the problems in your programs. It covers three topics:
- How to get the PHP interpreter to report the errors that interest you.
- How to locate basic syntax errors in your program.
- How to check the values of variables as your program is running.
Configuring Error Reporting
First of all, you need to configure the PHP interpreter so that when an error happens, you can see information about it. The error info can be sent along with program output to the web browser. It can also be included in the web server error log. A common way to set things up is to have error output go to the web browser when you're debugging your program, and then to the web server error log once the program is finished and (supposedly) working properly. That way, web site users can't see any potentially sensitive data included with error output.
To make error messages display in the browser, set the
display_errors
configuration directive to On
. To send
errors to the web server error log, set log_errors
to
On
. You can set them both to On
if you want error
messages in both places.
An error message that the PHP interpreter generates falls into one of five different categories:
- Parse error: A problem with the syntax of your program, such as leaving a semicolon off of the end of a statement. The interpreter stops running your program when it encounters a parse error.
- Fatal error: A severe problem with the content of your program, such as calling a function that hasn't been defined. The interpreter stops running your program when it encounters a fatal error.
- Warning: An advisory from the interpreter that something is fishy in your program, but the interpreter can keep going. Using the wrong number of arguments when you call a function causes a warning.
- Notice: A tip from the PHP interpreter, playing the role of Miss Manners. For example, printing a variable without first initializing it to some value generates a notice.
- Strict notice: An admonishment from the PHP interpreter about your coding style. Most of these have to do with esoteric features that changed between PHP 4 and PHP 5, so you're not likely to run into them too much.
You don't have to be notified about all of the different error categories.
The error_reporting
configuration directive controls which kinds of
errors the PHP interpreter reports. The default value for
error_reporting
is E_ALL & ~E_NOTICE &
~E_STRICT
, which tells the interpreter to report all errors except
notices and strict notices.
PHP defines some constants you can use to set the value of
error_reporting
so that only errors of certain types get reported:
E_ALL
(for all errors except strict notices), E_PARSE
(parse errors), E_ERROR
(fatal errors), E_WARNING
(warnings), E_NOTICE
(notices), and E_STRICT
(strict
notices).
Because strict notices are rare (and new to PHP 5), they are not included in
E_ALL
. To tell the PHP interpreter that you want to hear about
everything that could possibly be an error, set error_reporting
to
E_ALL | E_STRICT
.
Fixing Parse Errors
The first time you write a PHP program, you discover that the PHP interpreter is extremely picky. If you leave out a necessary semicolon or start a string with a single quote but end it with a double quote, the interpreter doesn't run your program. It throws up its (virtual) hands, complains about a parse error, and leaves you stuck in the debugging wilderness.
This can be one of the most frustrating things about programming when you're getting started. Everything has to be phrased and punctuated just so in order for the PHP interpreter to accept it. One thing that helps this process along is writing your programs in an editor that is PHP-aware, such as BBEdit, Emacs, XEmacs, Komodo, Dreamweaver, PHPEd, PHPEdit, or Zend Studio.
These editors do syntax highlighting. This is a feature that changes
the color of different parts of your program based on what those parts are. For
example, strings are pink, keywords such as if
and
while
are blue, comments are grey, and variables are black. Syntax
highlighting makes it easier to detect things like a string that's missing its
closing quote: the pink text continues past the line that the string is on, all
the way to the end of the file (or to the next quote that appears later in the
program).
Another feature of these editors is quote and bracket matching. This helps to
make sure that your quotes and brackets are balanced. When you type a closing
delimiter such as }
, the editor highlights the opening
{
that it matches. Different editors do this in different ways, but
typical methods are to flash the cursor at the location of the opening
{
, or bold the { }
pair for a short time. This
behavior is helpful for pairs of punctuation marks that go together: single and
double quotes that delimit strings, parentheses, square brackets, and curly
braces.
These editors also show the line numbers of your program files. When you get an error message from the PHP interpreter complaining about a parse error in line 35 in your program, you can focus on the right place to look for your error.
Parse errors happen when the PHP interpreter comes upon something unexpected in your program. Consider this broken program:
<?php
if $logged_in) {
print "Welcome, user.";
}
?>
When told to run that broken program, the PHP interpreter produces the following error message:
Parse error: parse error, unexpected T_VARIABLE, expecting '(' in
welcome.php on line 2
That error message means that in line 2 of the file, the PHP interpreter was
expecting to see an open parenthesis but instead, it encountered something
called T_VARIABLE
. That T_VARIABLE
thing is called a
token. It's the PHP interpreter's way of expressing different fundamental
parts of programs. When the interpreter reads in a program, it translates what
you've written into a list of tokens. Wherever you put a variable in your
program, there is a T_VARIABLE
token in the interpreter's list.
What the PHP interpreter is trying to tell you with the error message is "I
was reading line 2 and saw a variable where I was expecting an open
parenthesis." Looking at line 2 of the program, you can see why this is so: the
open parenthesis that should start the if()
test expression is
missing. After seeing if
, PHP expects a (
to start the
test expression. Since that's not there, it sees $logged_in
, a
variable, instead.
A list of all of the tokens that the PHP interpreter uses (and therefore that may show up in an error message) is in the PHP online manual at www.php.net/tokens.
The insidious thing about parse errors, though, is that the line number in the error message is often not the line where the error actually is. The following program has such an error in it:
<?php
$first_name = "David';
if ($logged_in) {
print "Welcome, $first_name";
} else {
print "Howdy, Stranger.";
}
?>
When it tries to run this program, the PHP interpreter says:
Parse error: parse error, unexpected T_STRING in welcome.php on line
4
That error makes it seem like line 4 contains a string in a place where it
shouldn't. But you can scrutinize line 4 all you want to find a problem with it,
and you won't find one. That line, print "Welcome, $first_name";
is
perfectly correct: the string is correctly delimited with double quotes and the
line appropriately ends with a semicolon.
The real problem in the program is in line 2. The string being assigned to
$first_name
starts with a double quote but "ends" with a single
quote. As the PHP interpreter reads line 2, it sees the double quote and thinks
"OK, here comes a string. I'll read everything until the next (unescaped) double
quote as the contents of this string." That makes the interpreter fly right over
the single quote in line 2 and keep going all the way until the first double
quote in line 4. When it sees that double quote, the interpreter thinks it's
found the end of the string. It then considers what happens after the double
quote to be a new command or statement. But what's after the double quote is
Welcome, $first_name";
. This doesn't make any sense to the
interpreter. It's expecting a semicolon to end a statement, or maybe a
.
to concatenate the just-defined string with another string. But
Welcome, $first_name";
is just an undelimited string sitting where
it doesn't belong. So the interpreter gives up and shouts out a parse error.
Imagine you're running down the streets of Manhattan at supersonic speed. The sidewalk on 35th street has some cracks in it, so you trip. But you're going so fast that you land on 39th street and dirty the pavement with your blood and guts. Then a traffic safety officer comes over and says, "Hey! There's a problem with 39th street! Someone's soiled the sidewalk with their innards!"
That's what the PHP interpreter is doing, in this case. The line number in the parse error is where the interpreter sees something it doesn't expect, which is not always the line number where the actual error is.
When you get a parse error from the interpreter, first take a look at the
line reported in the parse error. Check for the basics, such as making sure that
you've got a semicolon at the end of the statement. If the line seems OK, work
your way forward and back a few lines in the program to hunt down the actual
error. Pay special attention to punctuation that goes in pairs: single or double
quotes that delimit strings, parentheses in function calls or test expressions,
square brackets in array elements, and curly braces in code blocks. Count that
the number of opening punctuation marks (such as (
, [
,
and {
) matches the number of closing punctuation marks (such as
)
, ]
, and }
).
Inspecting Program Data
Once you clear the parse error hurdle, you still may have some work to do before you reach the finish line. A program can be syntactically correct but logically flawed. Just as the sentence "The tugboat chewed apoplectically with six subtle buffaloes" is grammatically correct but meaningless nonsense, you can write a program that the PHP interpreter doesn't find any problems with, but doesn't do what you expect.
If your program is acting funny, add some checkpoints that display the values of variables. That way, you can see where the program's behavior diverges from your expectations. The following program incorrectly attempts to calculate the total cost of a few items:
<?php
$prices = array(5.95, 3.00, 12.50);
$total_price = 0;
$tax_rate = 1.08; // 8% tax
foreach ($prices as $price) {
$total_price = $price * $tax_rate;
}
printf('Total price (with tax): $%.2f', $total_price);
?>
The program doesn't do the right thing. It prints:
Total price (with tax): $13.50
The total price of the items should be at least $20. What's wrong with the
program? One way you can try to find out is to insert a line in the
foreach()
loop that prints the value of $total_price
before and after it changes. That should provide some insight into why the math
is wrong. Here's a version of the program with some diagnostic
print
statements:
<php
$prices = array(5.95, 3.00, 12.50);
$total_price = 0;
$tax_rate = 1.08; // 8% tax
foreach ($prices as $price) {
print "[before: $total_price]";
$total_price = $price * $tax_rate;
print "[after: $total_price]";
}
printf('Total price (with tax): $%.2f', $total_price);
?>
This program prints:
[before: 0][after: 6.426][before: 6.426][after: 3.24][before:
3.24][after: 13.5]Total price (with tax): $13.50
From analyzing the debugging output, you can see that
$total_price
isn't increasing on each trip through the
foreach()
loop. Scrutinizing the code further leads you to the
conclusion that the line:
$total_price = $price * tax_rate;
should be
$total_price += $price * tax_rate;
Instead of =
, the assignment operator, the code needs
+=
, the increment-and-assign operator.
To include an array in debugging output, use var_dump()
. It
prints all of the elements in an array. Surround the output of
var_dump()
with HTML <pre></pre>
tags to
have it nicely formatted in your web browser. This line of code prints the
contents of all submitted form parameters with var_dump():
print '<pre>'; var_dump($_POST); print '</pre>';
Going Further
Once you've got error reporting set up as you like it, and you know how to
find parse errors, and you can inspect program data, you're on your way to a
fruitful debugging career. However, a fully fleshed-out PHP programmer's toolbox
consists of much more than just the tips in this article. Chapter 12 of
Learning PHP 5, "Debugging," includes some additional debugging
techniques. For more advanced debugging possibilities, check out PHP extensions
such as XDebug and apd
. Some of the PHP-aware
editors listed in this article also include integrated debugging
capabilities.
David Sklar is an independent consultant in New York City, the author of O'Reilly's Learning PHP 5, and a coauthor of PHP Cookbook.
In June 2004, O'Reilly Media, Inc., released Learning PHP 5.
-
Sample Chapter 8, "Remembering Users with Cookies and Sessions," is available free online.
-
You can also look at the Table of Contents, the Index, and the full description of the book.
-
For more information, or to order the book, click here.
Essential Reading Building
Tag Clouds in Perl and PHP
Tag clouds are everywhere on the web these days. First popularized by the web sites Flickr, Technorati, and del.icio.us, these amorphous clumps of words now appear on a slew of web sites as visual evidence of their membership in the elite corps of "Web 2.0." This PDF analyzes what is and isn't a tag cloud, offers design tips for using them effectively, and then goes on to show how to collect tags and display them in the tag cloud format. Scripts are provided in Perl and PHP. Yes, some have said tag clouds are a fad. But as you will see, tag clouds, when used properly, have real merits. More importantly, the skills you learn in making your own tag clouds enable you to make other interesting kinds of interfaces that will outlast the mercurial fads of this year or the next. Read Online--Safari Search this book on Safari: |
Return to the PHP DevCenter
Showing messages 1 through 6 of 6.
- PHP Debugging
Basics
2010-02-17 01:44:48 sangeeta11 [View]
- PHP Debugging
Basics
2010-02-16 22:43:03 sangeeta11 [View]
Same thing I am looking for the net and i got it!!! Thanks for this information
Online Sweepstakes (http://www.winprizesonline.com/)
- How for
Beginners
2009-02-01 05:37:06 joes [View]
Very informative but for absolute beginners it would be useful to explain *how* to to this following the sentence, "To make error messages display in the browser, set the display_errors configuration directive to On. To send errors to the web server error log, set log_errors to On. You can set them both to On if you want error messages in both places."
Joe
- very Good Tips
2007-02-18 05:11:34 netcharsi [View]
Its really good tips for me
mOOn
www.funpal.net
- Alternative to print_r() or
var_dump()
2004-08-16 02:20:08 lee102 [View]
found this nice alternative to the print_r() or var_dump() functions:
http://www.atomar.de/public/code/debuglib/debuglib.demo.php
not a "real" debugger but it saved me a lot of time :)
- Simple
debug_print_backtrace()
2004-08-15 06:53:13 AngryBeaver [View]
Perhaps, you should have introduceddebug_print_backtrace()
as well
It is available from PHP 5
Sweepstakes (http://www.winprizesonline.com/)