Error Types and Basic Debugging 242
Adjusting Error Reporting in PHP 250
Creating Custom Error Handlers 253
SQL and MySQL Debugging Techniques 262
If you’re working through this book sequentially (which would be for the best), the next subject to learn is how to use PHP and MySQL together. However, that process will undoubtedly generate errors, errors that can be tricky to debug. So before moving on to new concepts, these next few pages address the bane of the programmer: errors. As you gain experience, you’ll make fewer errors and learn your own debugging methods, but there are plenty of tools and techniques the beginner can use to help ease the learning process.
This chapter has three main threads. One focus is on learning about the various kinds of errors that can occur when developing dynamic Web sites and what their likely causes are. Second, a multitude of debugging techniques are taught, in a step-by-step format. Finally, you’ll see different techniques for handling the errors that do occur in the most graceful manner possible.
When developing Web applications with PHP and MySQL, you end up with potential bugs in one of four or more technologies. You could have HTML issues, PHP problems, SQL errors, or MySQL mistakes. The first step in fixing any bug is finding its source.
HTML problems are often the least disruptive and the easiest to catch. You normally know there’s a problem when your layout is all messed up. Some steps for catching and fixing these, as well as general debugging hints, are discussed in the next section.
PHP errors are the ones you’ll see most often, as this language will be at the heart of your applications. PHP errors fall into three general areas:
• Syntactical
• Run-time
• Logical
Syntactical errors are the most common and the easiest to fix. You’ll see them if you merely omit a semicolon. Such errors stop the script from executing, and if display_errors is on in your PHP configuration, PHP will show an error, including the line PHP thinks it’s on . If display_errors is off, you’ll see a blank page. (You’ll learn more about display_errors later in this chapter.)
Run-time errors include those things that don’t stop a PHP script from executing (like parse errors do) but do stop the script from doing everything it was supposed to do. Examples include calling a function using the wrong number or types of parameters. With these errors, PHP will normally display a message indicating the exact problem (again, assuming that display_errors is on).
The final category of error—logical—is actually the worst, because PHP won’t necessarily report it to you. These are out-and-out bugs: problems that aren’t obvious and don’t stop the execution of a script. Tricks for solving all of these PHP errors will be demonstrated in just a few pages.
SQL errors are normally a matter of syntax, and they’ll be reported when you try to run the query in MySQL. For example, I’ve done this too many times :
DELETE * FROM tablename
The syntax is just wrong, a confusion with the SELECT
syntax (SELECT * FROM
tablename
). The correct syntax is
DELETE FROM tablename
Again, MySQL will raise a red flag when you have SQL errors, so these aren’t that difficult to find and fix. With modern Web sites, the catch is that you don’t always have static queries, but often ones dynamically generated by PHP. In such cases, if there’s an SQL syntax problem, the issue is probably in your PHP code.
Besides reporting on SQL errors, MySQL has its own errors to consider. An inability to access the database is a common one and a showstopper at that . You’ll also see errors when you misuse a MySQL function or ambiguously refer to a column in a join. Again, MySQL will report any such error in specific detail. Keep in mind that when a query doesn’t return the records or otherwise have the result you expect, that’s not a MySQL or SQL error, but rather a logical one. Toward the end of this chapter you’ll see how to solve SQL and MySQL problems.
But as you have to walk before you can run, the next section covers the fundamentals of debugging dynamic Web sites, starting with the basic checks you should make and how to fix HTML problems.
This first sequence of steps may seem obvious, but when it comes to debugging, missing one of these steps leads to an unproductive and extremely frustrating debugging experience. And while I’m at it, I should mention that the best piece of general debugging advice is this:
When you get frustrated, step away from the computer!
I have solved almost all of the most perplexing issues I’ve come across by taking a break, clearing my head, and coming back to the code with fresh eyes. Readers in the book’s supporting forum (www.LarryUllman.com/forums/) have frequently found this to be true as well. Trying to forge ahead when you’re frustrated tends to make things worse. Much worse.
• Make sure that you are running the right page.
It’s altogether too common that you try to fix a problem and no matter what you do, it never goes away. The reason: you’ve actually been editing a different page than you thought. So verify that the name and location of the file being executed matches that of the file you’re editing. In this regard, using an all-in-one IDE, such as Adobe Dreamweaver (www.adobe.com/go/dreamweaver), is an advantage.
• Make sure that you have saved your latest changes.
An unsaved document will continue to have the same problems it had before you edited it (because the edits haven’t been enacted). One of the many reasons I like the TextMate (www.macromates.com) text editor is that it automatically saves every document when the application loses focus.
• Make sure that you run all PHP pages through the URL.
Because PHP works through a Web server (Apache, IIS, etc.), running any PHP code requires that you access the page through a URL (http://www.example.com/page.php or http://localhost/page.php
). If you double-click a PHP page to open it in a browser (or use the browser’s File > Open option), you’ll see the PHP code, not the executed result. This also occurs if you load an HTML page without going through a URL (which will work on its own) but then submit the form to a PHP page .
• Know what versions of PHP and MySQL you are running.
Some problems are specific to a certain version of PHP or MySQL. For example, some functions are added in later versions of PHP, and MySQL added significant new features in versions 4, 4.1, and 5. Run a phpinfo( )
script , (see Appendix A, “Installation,” for a script example) and open a mysql client session to determine this information. phpMyAdmin will often report on the versions involved as well (but don’t confuse the version of phpMyAdmin, which will likely be 3.something, with the versions of PHP or MySQL).
I consider the versions being used to be such an important, fundamental piece of information that I won’t normally assist people looking for help until they provide this information!
• Know what Web server you are running.
Similarly, some problems and features are unique to your Web serving application—Apache, IIS, or Abyss. You should know which one you are using, and which version, from when you installed the application. If you’re using a Web host, the hosting company can provide you with this information.
• Try executing pages in a different Web browser.
Every Web developer should have and use at least two Web browsers. If you test your pages in different ones, you’ll be able to see if the problem has to do with your script or a particular browser. Normally, only HTML and CSS problems can arise (or disappear) when you switch browsers; rarely will PHP, let alone MySQL or SQL, errors be browser specific.
• If possible, try executing the page using a different Web server, version of PHP, and/or version of MySQL.
PHP and MySQL errors sometimes stem from particular configurations and versions on one server. If something works on one server but not another, then you’ll know that the script isn’t inherently at fault. From there it’s a matter of using phpinfo( )
scripts to see what server settings may be different.
If taking a break is one thing you should do when you become frustrated, here’s what you shouldn’t do: send off one or multiple panicky and persnickety emails to a writer, to a newsgroup or mailing list, or to anyone else. When it comes to asking for free help from strangers, patience and pleasantries garner much better and faster results.
For that matter, I would strongly advise against randomly guessing at solutions. I’ve seen far too many people only complicate matters further by taking stabs at solutions, without a full understanding of what the attempted changes should or should not do.
There’s another different realm of errors that you could classify as usage errors: what goes wrong when the site’s user doesn’t do what you thought they would. As a golden rule, write your code so that it doesn’t break even if the user doesn’t do anything right or does everything wrong! In other words, make no assumptions. There’s a quote from Doug Linder that applies here: “A good programmer is someone who looks both ways before crossing a one-way street.”
Debugging HTML is relatively easy. The source code is very accessible, most problems are overt, and attempts at fixing the HTML don’t normally make things worse (as can happen with PHP). Still, there are some basic steps you should follow to find and fix an HTML problem.
• Check the source code.
If you have an HTML problem, you’ll almost always need to check the source code of the page to find it. How you view the source code depends upon the browser being used, but normally it’s a matter of using something like View > Page Source or View > Source.
• Use a validation tool .
Validation tools, like the one at http://validator.w3.org, are great for finding mismatched tags, broken tables, and other problems.
• Use Firefox.
I’m not trying to start a discussion on which is the best Web browser, and as Internet Explorer is (still!) the most used one, you’ll need to eventually test using it, but I personally find that Firefox (available for free from www.mozilla.com) is the best Web browser for Web developers. Firefox offers reliability and debugging features not available in other browsers. If you want to stick with IE or Safari for your day-to-day browsing, that’s up to you, but when doing Web development, turn to Firefox.
• Use Firefox’s add-on widgets .
Besides being just a great Web browser, the very popular Firefox browser has a ton of features that the Web developer will appreciate. Furthermore, you can expand Firefox’s functionality by installing any of the free widgets that are available. The Web Developer widget in particular provides quick access to great tools, such as showing a table’s borders, revealing the CSS, validating a page, and more. I also frequently use these add-ons: Firebug, DOM Inspector, and HTML Validator, among others.
• Test the page in another browser.
PHP code is generally browser-independent, meaning you’ll get consistent results regardless of the client. Not so with HTML. Sometimes a particular browser has a quirk that affects the rendered page. Running the same page in another browser is the easiest way to know if it’s an HTML problem or a browser quirk.
The first step toward fixing any kind of problem is understanding what’s causing it. Remember the role each technology—HTML, PHP, SQL, and MySQL—plays as you debug. If your page doesn’t look right, that’s an HTML problem. If your HTML is dynamically generated by PHP, it’s still an HTML problem, but you’ll need to work with the PHP code to make it right.
PHP provides remarkably useful and descriptive error messages when things go awry. Unfortunately, PHP doesn’t show these errors when running using its default configuration. This policy makes sense for live servers, where you don’t want the end users seeing PHP-specific error messages, but it also makes everything that much more confusing for the beginning PHP developer. To be able to see PHP’s errors, you must turn on the display_errors directive, either in an individual script or for the PHP configuration as a whole.
To turn on display_errors in a script, use the ini_set( )
function. As its arguments, this function takes a directive name and what setting that directive should have:
ini_set('display_errors', 1);
Including this line in a script will turn on display_errors for that script. The only downside is that if your script has a syntax error that prevents it from running at all, then you’ll still see a blank page. To have PHP display errors for the entire server, you’ll need to edit its configuration, as is discussed in the “Configuring PHP” section of Appendix A.
1. Create a new PHP document in your text editor or IDE, to be named display_errors.php
(Script 8.1):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
<title>Displaying Errors</title>
</head>
<body>
<h2>Testing Display Errors</h2>
<?php # Script 8.1 - display_errors.php
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML
1.0 Transitional//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/
xhtml1-transitional.dtd">
3 <html xmlns="http://www.w3.org/1999/
xhtml" xml:lang="en" lang="en">
4 <head>
5 <meta http-equiv="Content-Type"
content="text/html; charset=utf-8" />
6 <title>Displaying Errors</title>
7 </head>
8 <body>
9 <h2>Testing Display Errors</h2>
10 <?php # Script 8.1 - display_errors.php
11
12 // Show errors:
13 ini_set('display_errors', 1);
14
15 // Create errors:
16 foreach ($var as $v) {}
17 $result = 1/0;
18
19 ?>
20 </body>
21 </html>
2. After the initial PHP tags, add:
ini_set('display_errors', 1);
From this point in this script forward, any errors that occur will be displayed.
3. Create some errors:
foreach ($var as $v) { }
$result = 1/0;
To test the display_errors setting, the script needs to have at least one error. This first line doesn’t even try to do anything, but it’s guaranteed to cause an error. There are actually two issues here: first, there’s a reference to a variable ($var
) that doesn’t exist; second, a non-array ($var
) is being used in the foreach
loop as if it were an array.
The second line is a classic division by zero, which is not allowed in programming languages or in math.
4. Complete the page:
?>
</body>
</html>
5. Save the file as display_errors.php
, place it in your Web directory, and test it in your Web browser .
6. If you want, change the first line of PHP code to read:
ini_set('display_errors', 0);
Then save and retest the script .
There are limits as to what PHP settings the ini_set( )
function can be used to adjust. See the PHP manual for specifics as to what can and cannot be changed using it.
As a reminder, changing the display_errors setting in a script only works so long as that script runs (i.e., it cannot have any parse errors). To be able to always see any errors that occur, you’ll need to enable display_errors in PHP’s configuration file (again, see the appendix).
Once you have PHP set to display the errors that occur, you might want to adjust the level of error reporting. Your PHP installation as a whole, or individual scripts, can be set to report or ignore different types of errors. Table 8.1 lists most of the levels, but they can generally be one of these three kinds:
• Notices, which do not stop the execution of a script and may not necessarily be a problem.
• Warnings, which indicate a problem but don’t stop a script’s execution.
• Errors, which stop a script from continuing (including the ever-common parse error, which prevents scripts from running at all).
As a rule of thumb, you’ll want PHP to report on any kind of error while you’re developing a site but report no specific errors once the site goes live. For security and aesthetic purposes, it’s generally unwise for a public user to see PHP’s detailed error messages.
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML
1.0 Transitional//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/
xhtml1-transitional.dtd">
3 <html xmlns="http://www.w3.org/1999/
xhtml" xml:lang="en" lang="en">
4 <head>
5 <meta http-equiv="Content-Type"
content="text/html; charset=utf-8" />
6 <title>Reporting Errors</title>
7 </head>
8 <body>
9 <h2>Testing Error Reporting</h2>
10 <?php # Script 8.2 - report_errors.php
11
12 // Show errors:
13 ini_set('display_errors', 1);
14
15 // Adjust error reporting:
16 error_reporting(E_ALL | E_STRICT);
17
18 // Create errors:
19 foreach ($var as $v) {}
20 $result = 1/0;
21
22 ?>
23 </body>
24 </html>
Frequently, error messages—particularly those dealing with the database—will reveal certain behind-the-scenes aspects of your Web application that are best not shown. While you hope all of these will be worked out during the development stage, that may not be the case.
You can universally adjust the level of error reporting following the instructions in Appendix A. Or you can adjust this behavior on a script-by-script basis using the error_reporting( )
function. This function is used to establish what type of errors PHP should report on within a specific page. The function takes either a number or a constant, using the values in Table 8.1 (the PHP manual lists a few others, related to the core of PHP itself).
error_reporting(0); // Show no errors.
A setting of 0 turns error reporting off entirely (errors will still occur; you just won’t see them anymore). Conversely, error_reporting (E_ALL)
will tell PHP to report on every error that occurs. The numbers can be added up to customize the level of error reporting, or you could use the bitwise operators—|
(or), ~
(not), &
(and)—with the constants. With this following setting, any non-notice error will be shown:
error_reporting (E_ALL & ~E_NOTICE);
1. Open display_errors.php
(Script 8.1) in your text editor or IDE, if it is not already.
To play around with error reporting levels, use display_errors.php
as an example.
2. After adjusting the display_errors setting, add (Script 8.2):
error_reporting(E_ALL | E_STRICT);
For development purposes, have PHP notify you of all errors, notices, warnings, and recommendations. Setting the level of error reporting to E_ALL
will accomplish that. But E_ALL
does not include E_STRICT
, so another clause—| (or) E_STRICT
—is added.
In short, now PHP will let you know about anything that is, or just may be, a problem.
Because E_ALL
and E_STRICT
are constants, they are not enclosed in quotation marks.
3. Save the file as report_errors.php
, place it in your Web directory, and run it in your Web browser .
I also altered the page’s title and the heading, but both are immaterial to the point of this exercise.
4. Change the level of error reporting to something different and retest and .
Because you’ll often want to adjust the display_errors and error_reporting for every page in a Web site, you might want to place those lines of code in a separate PHP file that can then be included by other PHP scripts.
The scripts in this book were all written with PHP’s error reporting on the highest level (with the intention of catching every possible problem).
The trigger_error( )
function is a way to programmatically generate an error in a PHP script. Its first argument is an error message; its second, optional, argument is a numeric error type, corresponding to the values in Table 8.1. By default the type will be E_USER
.
if (/* some condition */) {
trigger_error('Something Bad Happened!'),
}
Another option for error management with your sites is to alter how PHP handles errors. By default, if display_errors is enabled and an error is caught (that falls under the level of error reporting), PHP will print the error, in a somewhat simplistic form, within some minimal HTML tags .
You can override how errors are handled by creating your own function that will be called when errors occur. For example,
function report_errors (arguments) {
// Do whatever here.
}
set_error_handler ('report_errors'),
The PHP set_error_handler( )
function is used to name the user-defined function to be called when an error occurs. The handling function (report_errors, in this case) will, at that time, receive several values that can be used in any possible manner.
This function can be written to take up to five arguments. In order, these arguments are: an error number (corresponding to Table 8.1), a textual error message, the name of the file where the error was found, the specific line number on which it occurred, and the variables that existed at the time of the error. Defining a function that accepts all these arguments might look like
function report_errors ($num, $msg, $file, $line, $vars) {...
To make use of this concept, the report_errors.php
file (Script 8.2) will be rewritten one last time.
1. Open report_errors.php
(Script 8.2) in your text editor or IDE, if it is not already.
2. Remove the ini_set( )
and error_reporting( )
lines (Script 8.3).
When you establish your own error-handling function, the error reporting levels no longer have any meaning, so the line that adjusts them can be removed. Adjusting the display_errors setting is also meaningless, as the error-handling function will control whether errors are displayed or not.
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6 <title>Handling Errors</title>
7 </head>
8 <body>
9
10 <h2>Testing Error Handling</h2>
11 <?php # Script 8.3 - handle_errors.php
12
13 // Flag variable for site status:
14 define('LIVE', FALSE);
15
16 // Create the error handler:
17 function my_error_handler ($e_number, $e_message, $e_file, $e_line, $e_vars) {
18
19 // Build the error message:
20 $message = "An error occurred in script '$e_file' on line $e_line: $e_message
";
21
22 // Append $e_vars to $message:
23 $message .= print_r ($e_vars, 1);
24
25 if (!LIVE) { // Development (print the error).
26 echo '<pre>' . $message . "
";
27 debug_print_backtrace( );
28 echo '</pre><br />';
29 } else { // Don't show the error.
30 echo '<div class="error">A system error occurred. We apologize for the
inconvenience.</div><br />';
31 }
32
33 } // End of my_error_handler( ) definition.
34
35 // Use my error handler:
36 set_error_handler ('my_error_handler'),
37
38 // Create errors:
39 foreach ($var as $v) {}
40 $result = 1/0;
41
42 ?>
43 </body>
44 </html>
3. Before the script creates the errors, add:
define ('LIVE', FALSE);
This constant will be a flag used to indicate whether or not the site is currently live. It’s an important distinction, as how you handle errors and what you reveal in the browser should differ greatly when you’re developing a site and when a site is live.
This constant is being set outside of the function for two reasons. First, I want to treat the function as a black box that does what I need it to do without having to go in and tinker with it. Second, in many sites, there might be other settings (like the database connectivity information) that are also live versus development-specific. Conditionals could, therefore, also refer to this constant to adjust those settings.
4. Begin defining the error-handling function:
function my_error_handler ($e_number, $e_message, $e_file, $e_line, $e_vars) {
The my_error_handler( )
function is set to receive the full five arguments that a custom error handler can.
5. Create the error message using the received values.
$message = "An error occurred in script '$e_file' on line $e_line: $e_message ";
The error message will begin by referencing the filename and line number where the error occurred. Added to this is the actual error message. All of these values are passed to the function when it is called (when an error occurs).
6. Add any existing variables to the error message:
$message .= print_r ($e_vars, 1);
The $e_vars
variable will receive all of the variables that exist, and their values, when the error happens. Because this might contain useful debugging information, it’s added to the message.
The print_r( )
function is normally used to print out a variable’s structure and value; it is particularly useful with arrays. If you call the function with a second argument (1 or TRUE), the result is returned instead of printed. So this line adds all of the variable information to $message
.
7. Print a message that will vary, depending upon whether or not the site is live:
if (!LIVE) {
echo '<pre>' . $message . "
";
debug_print_backtrace( );
echo '</pre><br />';
} else {
echo '<div class="error">A system error occurred. We apologize for the inconvenience.</div><br />';
}
If the site is not live (if LIVE
is FALSE
), which would be the case while the site is being developed, a detailed error message should be printed . For ease of viewing, the error message is printed within HTML PRE
tags. Furthermore, a useful debugging function, debug_print_backtrace( )
, is also called. This function returns a slew of information about what functions have been called, what files have been included, and so forth.
If the site is live, a simple mea culpa will be printed, letting the user know that an error occurred but not what the specific problem is . Under this situation, you could also use the error_log( )
function (see the sidebar) to have the detailed error message emailed or written to a log.
8. Complete the function and tell PHP to use it:
}
set_error_handler('my_error_handler'),
This second line is the important one, telling PHP to use the custom error handler instead of PHP’s default handler.
9. Save the file as handle_errors.php
, place it in your Web directory, and test it in your Web browser .
10. Change the value of LIVE
to TRUE, save, and retest the script .
To see how the error handler behaves with a live site, just change this one value.
If your PHP page uses special HTML formatting—like CSS tags to affect the layout and font treatment—add this information to your error reporting function.
Obviously in a live site you’ll probably need to do more than apologize for the inconvenience (particularly if the error significantly affects the page’s functionality). Still, this example demonstrates how you can easily adjust error handling to suit the situation.
If you don’t want the error-handling function to report on every notice, error, or warning, you could check the error number value (the first argument sent to the function). For example, to ignore notices when the site is live, you would change the main conditional to
if (!LIVE) {
echo '<pre>' . $message . "
";
debug_print_backtrace( );
echo '</pre><br />';
} elseif ($e_number != E_NOTICE) {
echo '<div class="error">A system error occurred. We apologize for the inconvenience.</div><br />';
}
When it comes to debugging, what you’ll best learn from experience are the causes of certain types of errors. Understanding the common causes will shorten the time it takes to fix errors. To expedite the learning process, Table 8.2 lists the likely reasons for the most common PHP errors.
The first, and most common, type of error that you’ll run across is syntactical and will prevent your scripts from executing. An error like this will result in messages like the one in , which every PHP developer has seen too many times. To avoid making this sort of mistake when you program, be sure to:
• End every statement (but not language constructs like loops and conditionals) with a semicolon.
• Balance all quotation marks, parentheses, curly braces, and square brackets (each opening character must be closed).
• Be consistent with your quotation marks (single quotes can be closed only with single quotes and double quotes with double quotes).
• Escape, using the backslash, all single-and double-quotation marks within strings, as appropriate.
One thing you should also understand about syntactical errors is that just because the PHP error message says the error is occurring on line 12, that doesn’t mean that the mistake is actually on that line. At the very least, it is not uncommon for there to be a difference between what PHP thinks is line 12 and what your text editor indicates is line 12. So while PHP’s direction is useful in tracking down a problem, treat the line number referenced as more of a starting point than an absolute.
If PHP reports an error on the last line of your document, this is almost always because a mismatched parenthesis, curly brace, or quotation mark was not caught until that moment.
The second type of error you’ll encounter results from misusing a function. This error occurs, for example, when a function is called without the proper arguments. This error is discovered by PHP when attempting to execute the code. In later chapters you’ll probably see such errors when using the header( )
function, cookies, or sessions.
To fix errors, you’ll need to do a little detective work to see what mistakes were made and where. For starters, though, always thoroughly read and trust the error message PHP offers. Although the referenced line number may not always be correct, a PHP error is very descriptive, normally helpful, and almost always 100 percent correct.
• Turn on display_errors.
Use the earlier steps to enable display_errors for a script, or, if possible, the entire server, as you develop your applications.
• Use comments.
Just as you can use comments to document your scripts, you can also use them to rule out problematic lines. If PHP is giving you an error on line 12, then commenting out that line should get rid of the error. If not, then you know the error is elsewhere. Just be careful that you don’t introduce more errors by improperly commenting out only a portion of a code block: the syntax of your scripts must be maintained.
• Use the print
and echo
functions.
In more complicated scripts, I frequently use echo
statements to leave me notes as to what is happening as the script is executed . When a script has several steps, it may not be easy to know if the problem is occurring in step 2 or step 5. By using an echo
statement, you can narrow the problem down to the specific juncture.
• Check what quotation marks are being used for printing variables.
It’s not uncommon for programmers to mistakenly use single quotation marks and then wonder why their variables are not printed properly. Remember that single quotation marks treat text literally and that you must use double quotation marks to print out the values of variables.
• Track variables .
It is pretty easy for a script not to work because you referred to the wrong variable or the right variable by the wrong name or because the variable does not have the value you would expect. To check for these possibilities, use the print
or echo
statements to print out the values of variables at important points in your scripts. This is simply a matter of
echo "<p>$var = $var</p>
";
or
echo "<p>$var is $var</p>
";
The first dollar sign is escaped so that the variable’s name is printed. The second reference of the variable will print its value.
• Print array values.
For more complicated variable types (arrays and objects), the print_r( )
and var_dump( )
functions will print out their values without the need for loops. Both functions accomplish the same task, although var_dump( )
is more detailed in its reporting than print_r( )
.
Many text editors include utilities to check for balanced parentheses, brackets, and quotation marks.
If you cannot find the parse error in a complex script, begin by using the /* */
comments to render the entire PHP code inert. Then continue to uncomment sections at a time (by moving the opening or closing comment characters) and rerun the script until you deduce what lines are causing the error. Watch how you comment out control structures, though, as the curly braces must continue to be matched in order to avoid parse errors. For example:
if (condition) {
/* Start comment.
Inert code.
End comment. */
}
To make the results of print_r( )
more readable in the Web browser, wrap it within HTML <pre>
(preformatted) tags. This one line is one of my favorite debugging tools:
echo '<pre>' . print_r ($var, 1) . '</pre>';
The most common SQL errors are caused by the following issues:
• Unbalanced use of quotation marks or parentheses
• Unescaped apostrophes in column values
• Misspelling a column name, table name, or function
• Ambiguously referring to a column in a join
• Placing a query’s clauses (WHERE
, GROUP BY
, ORDER BY
, LIMIT
) in the wrong order
Furthermore, when using MySQL you can also run across the following:
• Unpredictable or inappropriate query results
• Inability to access the database
Since you’ll be running the queries for your dynamic Web sites from PHP, you need a methodology for debugging SQL and MySQL errors within that context (PHP will not report a problem with your SQL).
To decide if you are experiencing a MySQL (or SQL) problem rather than a PHP one, you need a system for finding and fixing the issue. Fortunately, the steps you should take to debug MySQL and SQL problems are easy to define and should be followed without thinking. If you ever have any MySQL or SQL errors to debug, just abide by this sequence of steps.
To hammer the point home, this next sequence of steps is probably the most useful debugging technique in this chapter and the entire book. You’ll likely need to follow these steps in any PHP-MySQL Web application when you’re not getting the results you expected.
1. Print out any applicable queries in your PHP script .
As you’ll see in the next chapter, SQL queries will often be assigned to a variable, particularly when you use PHP to dynamically create them. Using the code echo $query
(or whatever the query variable is called) in your PHP scripts, you can send to the browser the exact query being run. Sometimes this step alone will help you see what the real problem is.
2. Run the query in the mysql client or other tool .
The most foolproof method of debugging an SQL or MySQL problem is to run the query used in your PHP scripts through an independent application: the mysql client, phpMyAdmin, or the like. Doing so will give you the same result as the original PHP script receives but without the overhead, hassle, or mystery.
If the independent application returns the expected result but you are still not getting the proper behavior in your PHP script, then you will know that the problem lies within the script itself, not your SQL command or the MySQL database.
3. If the problem still isn’t evident, rewrite the query in its most basic form, and then keep adding dimensions back in until you discover which clause is causing the problem. Continue to use a third-party interface to MySQL to do this (i.e., put away the PHP script until you’ve got the SQL query working properly).
Sometimes it’s difficult to debug a query because there’s too much going on. Like commenting out most of a PHP script, taking a query down to its bare minimum structure and slowly building it back up can be the easiest way to debug complex SQL commands.
Access-denied error messages are the most common problem beginning developers encounter when using PHP to interact with MySQL. These are among the common solutions:
• Reload MySQL after altering the privileges so that the changes take effect. Either use the mysqladmin tool or run FLUSH PRIVILEGES
in the mysql client. You must be logged in as a user with the appropriate permissions to do this (see Appendix A for more).
• Double-check the password used. The error message Access denied for user: ‘user@localhost’ (Using password: YES) frequently indicates that the password is wrong or mistyped. (This is not always the cause but is the first thing to check.)
• The error message Can’t connect to... (error number 2002) indicates that MySQL either is not running or is not running on the socket or TCP/IP port tried by the client.
MySQL keeps its own error logs, which are very useful in solving MySQL problems (like why MySQL won’t even start). MySQL’s error log will be located in the MySQL data directory and titled hostname.err
.
The MySQL manual is very detailed, containing SQL examples, function references, and the meanings of error codes. Make the manual your friend and turn to it when confusing errors pop up.
If you have any problems with the review questions or the pursue prompts, turn to the book’s supporting forum (www.LarryUllman.com/forums/).
• Why must PHP scripts be run through a URL?
• What version of PHP are you using? What version of MySQL? What version of what Web server application are you using? On what operating system?
• What debugging steps should you take if the rendered Web page doesn’t look right in your Web browser?
• Do you have display_errors enabled on your server? Why is enabling display_errors useful on development servers? Why is revealing errors a bad thing on production servers?
• How does the level of error_reporting affect PHP scripts? To what level of error_reporting is your PHP server set?
• What does the @
operator do?
• What are the benefits of using your own error-handling function? What impact does the error reporting level have when using your own error-handling function?
• How can print
or echo
be used as debugging tools? Hint: There are many correct answers.
• What is the method for fixing PHP-SQL-MySQL bugs?
• Install the Firebug and Web Developer extensions for Firefox, if you have not already. Install Firefox if you haven’t already installed it!
• Enable display_errors on your development server, if you can.
• If you can, set PHP’s level of error reporting to E_ALL | E_STRICT
on your development server.
• Check out the PHP manual’s page for the debug_print_backtrace( )
function to learn more about it.
• Consider using a professional-grade IDE that provides built-in debugging tools.
52.15.117.231