It also takes careful testing to simulate each class of runtime error that might occur.. MySQL for example can provide one of around 200 different error num-bers and messages.You do need
Trang 1462 Chapter 23 Debugging
cannot automatically tell you that a particular line will generate an error.Your testing needs to provide one of the situations that create the error
Handling runtime errors requires a certain amount of forethought; to check for dif-ferent types of failure that might occur, and then take appropriate action It also takes careful testing to simulate each class of runtime error that might occur
This does not mean that you need to attempt to simulate every different error that might occur MySQL for example can provide one of around 200 different error num-bers and messages.You do need to simulate an error in each function call that is likely to result in an error, and an error of each type that is handled by a different block of code
Failure to Check Input Data
Often we make assumptions about the input data that will be entered by users If this data does not fit our expectations, it might cause an error, either a runtime error or a logic error (detailed in the following section)
A classic example of a runtime error occurs when we are dealing with user input data and we forget to AddSlashes()to it.This means if we have a user with a name such as O’Grady that contains an apostrophe, we will get an error from the database function
We will talk more about errors because of assumptions about input data in the next sec-tion
Logic Errors
Logic errors can be the hardest type of error to find and eliminate.This type of error is where perfectly valid code does exactly what it is instructed to do, but that was not what the writer intended
Logic errors can be caused by a simple typing error, such as:
for ( $i = 0; $i < 10; $i++ );
{ echo 'doing something<br />';
}
This snippet of code is perfectly valid It follows valid PHP syntax It does not rely on any external services, so it is unlikely to fail at runtime Unless you looked at it very carefully, it probably will not do what you think it will or what the programmer
intend-ed it to do
At a glance, it looks as if it will iterate through the forloop ten times, echoing
“doing something"each time
The addition of an extraneous semicolon at the end of the first line means that the loop has no effect on the following lines.The forloop will iterate ten times with no result, and then the echostatement will be executed once
Because this code is a perfectly valid, but inefficient, way to write code to achieve this result, the parser will not complain Computers are very good at some things, but they
do not have any common sense or intelligence A computer will do exactly as it is told You need to make sure that what you tell it is exactly what you want
Trang 2Logic errors are not caused by any sort of failure of the code, but merely a failure of the programmer to write code that instructs the computer to do exactly what he
want-ed As a result, errors cannot be detected automatically.You will not be told that an error has occurred, and you will not be given a line number to look for the problem at Logic errors will be detected only by proper testing
A logic error such as the previous trivial example is fairly easy to make, but also easy
to correct as the first time your code runs you will see output other than what you expected Most logic errors are a little more insidious
Troublesome logic errors usually result from developers’ assumptions being wrong
Chapter 22, “Using PHP and MySQL for Large Projects,” recommended using other developers to review code to suggest additional test cases, and using people from the tar-get audience rather than developers for testing Assuming that people will enter only cer-tain types of data is very easy to do and very easy to leave undetected if you do your own testing
Let’s say that you have an Order Quantity text box on a commerce site Have you assumed that people will only enter positive numbers? If a visitor enters negative ten, will your software refund his credit card with ten times the price of the item?
Suppose that you have a box to enter a dollar amount Do you allow people to enter the amount with or without a dollar sign? Do you allow people to enter numbers with thousands separated by commas? Some of these things can be checked at client-side (using, for example, JavaScript) to take a little load off your server
If you are passing information to another page, has it occurred to you that there might be characters that have special significance in a URL such as spaces in the string you are passing?
An infinite number of logic errors is possible.There is no automated way to check for them.The only solution is, first, to try to eliminate assumptions that you have implicitly coded into the script and, second, test thoroughly with every type of valid and invalid input possible, ensuring that you get the anticipated result for all
Variable Debugging Aid
As projects get more complex, it can be useful to have some utility code to help you identify the cause of errors A piece of code that you might find useful is contained in Listing 23.1.This code will echo the contents of variables passed to your page
Listing 23.1 dump_variables.php—This Code Can Be Included in Pages to Dump the
Contents of Variables for Debugging
<?php // these lines format the output as HTML comments // and call dump_array repeatedly
Trang 3464 Chapter 23 Debugging
echo '<! BEGIN GET VARS >\n';
echo '<! '.dump_array($HTTP_GET_VARS).' >\n';
echo '<! BEGIN POST VARS >\n';
echo '<! '.dump_array($HTTP_POST_VARS).' >\n';
echo '<! BEGIN SESSION VARS >\n';
echo '<! '.dump_array($HTTP_SESSION_VARS).' >\n';
echo '<! BEGIN COOKIE VARS >\n';
echo '<! '.dump_array($HTTP_COOKIE_VARS).' >\n';
echo '\n<! END VARIABLE DUMP >\n';
// dump_array() takes one array as a parameter // It iterates through that array, creating a string // to represent the array as a set
function dump_array($array) {
if(is_array($array)) {
$size = count($array);
$string = '';
if($size) {
$count = 0;
$string = '{ ';
// add each element's key and value to the string foreach($array as $var => $value)
{
$string = “$var = $value";
if($count++ < ($size-1)) {
$string = ', ';
} }
$string = ' }';
} return $string;
} else {
Listing 23.1 Continued
Trang 4return $array;
} }
?>
This code will iterate through four arrays of variables that a page receives If a page was called with GET variables, POST variables, cookies, or has session variables, these will be output
A line of HTML will be generated for each type of variable
The lines will resemble this:
<! { var1 = 'value1', var2 = 'value2', var3 = 'value3' } >
We have put the output within an HTML comment so that it is viewable, but will not interfere with the way that the browser renders visible page elements.This is a good way
to generate debugging information
The exact output will depend on the variables passed to the page, but when added to Listing 20.4, one of the authentication examples from Chapter 20, “Using Session Control in PHP,” it adds the following lines to the HTML generated by the script:
<! BEGIN VARIABLE DUMP >
<! BEGIN GET VARS >
<! >
<! BEGIN POST VARS >
<! { userid = testuser, password = test123 } >
<! BEGIN SESSION VARS >
<! { valid_user = testuser } >
<! BEGIN COOKIE VARS >
<! { PHPSESSID = 2552dc82bb465af56d65e9300f75fd68 } >
<! END VARIABLE DUMP >
You can see that it is displaying the POST variables sent from the login form on the previous page—useridand password It is also showing the session variable that we are using to keep the user’s name in—valid_user As discussed in Chapter 20, PHP uses a cookie to link session variables to particular users Our script is echoing the pseudo-ran-dom number,PHPSESSID, which is stored in that cookie to identify a particular user
Error Reporting Levels
PHP allows you to set how fussy it should be with errors.You can modify what types of events will generate messages By default, PHP will report all errors other than notices
The error reporting level is set using a set of predefined constants, shown in Table 23.1
Listing 23.1 Continued
Trang 5466 Chapter 23 Debugging
Table 23.1 Error Reporting Constants Value Name Meaning
1 E_ERROR Report fatal errors at runtime
2 E _ WARNING Report nonfatal errors at runtime
8 E_NOTICE Report notices, notifications that something you have
done might be an error
16 E_CORE_ERROR Report failures in the startup of the PHP engine
32 E_CORE_WARNING Report nonfatal failures during the startup of the PHP
engine
64 E_COMPILE_ERROR Report errors in compilation
128 E_COMPILE_WARNING Report nonfatal errors in compilation
256 E_USER_ERROR Report user triggered errors
512 E_USER_WARNING Report user triggered warnings
1024 E_USER_NOTICE Report user triggered notices
2048 E_ALL Report all errors and warnings
Each constant represents a type of error that can be reported or ignored If for instance, you specify the error level as E_ERROR, only fatal errors will be reported.These constants can be combined using binary arithmetic, to produce different error levels
The default error level, report all errors other than notices, is specified as
E_ALL & ~E_NOTICE
This expression consists of two of the predefined constants combined using bitwise arithmetic operators.The ampersand (&) is the bitwise AND operator and the tilde (~) is the bitwise NOT operator.This expression can be read as E_ALLAND NOT E_NOTICE
E_ALLitself is effectively a combination of all the other error types It could be replaced by the other levels ORed together using the bitwise OR operator (|)
E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR |E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE
Similarly, the default error reporting level could be specified by all error levels except notice ORed together
E_ERROR | E_WARNING | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE