In this section we're going to look at techniques to make debugging quicker and easier, and we demonstrate some functions you can use to give you more information about your script.
Creating a Custom Debugging FunctionOne of the best debugging techniques, and also one of the simplest, is using the PHP echo() function.
Using echo() To Output Useful InformationAs echo() is not actually a function, but a language construct, it can be used with or without parentheses, although if you want to output more than one parameter, you cannot use the parentheses. When you're tracking down errors in complicated blocks of code in which a lot of variables are being used, it can be hard to understand what is happening as, although you can see the variables, you cannot see what they will contain while the code is running. It makes life a lot easier if you add extra statements to your code, which send the contents of the variables to the screen. It's a good idea to output the line in the following format:
echo "\$Stringname: $string <br>"; Note the backslash, \, which has to be included to escape the $ character. This means that the PHP engine won't treat it as a variable, and will instead send it to the screen as text. So for example, for a variable called $testvalue, we would use:
echo "\$testValue : $testvalue <br>"; When the page is opened in the browser, it shows: $testValue: 25 It is well worth adding a number of these statements, so you can track the value of the variable through the flow of your script. This can be extremely useful, and you will often find that the value of a variable is not what you were expecting. For instance, if we take the following fragment of code:
<?php $total = $cartTotal; $result = addVAT($total); $result = addPackaging($result); $result = applyDiscount($result); ?> which could be used to generate a final total for invoice, the variable $result is run through a number of different custom functions. If when the code was run, the end total is incorrect, it's difficult to see exactly where in the code the error is occurring. By adding extra echo statements, as in the following code:
<?php $total = $cartTotal; echo "\$total: $total <br>"; $result = addPackaging($result); echo "addPackaging \$result: $result <br>"; $result = applyDiscount($result); echo "applyDiscount \$result: $result <br>"; $result = addVAT($total); echo "addVAT \$result: $result <br>"; echo "Total Price: £$result <br>"; ?> It would produce output similar to the following: $total: 100.75 addPackaging $result: 110.75 applyDiscount $result: 0.355 addVAT $result: 0.41 Total Price: £0.41 By displaying the variable $result as it moves through the different functions, you can see where the error occurs, in the above case the result from the addDiscount function is incorrect, so you would take a closer look at the code in that function.
Adding to the Debug Information with gettype()We can now expand on this using the PHP gettype() function. This function is passed a variable as a parameter, and returns the variable's type: integer, string, etc. So we can modify our statement to include the gettype() function:
echo "\$testValue : $testvalue : " . gettype($testValue) . " <br> "; Now when the page is opened in a browser, it shows: $testValue : 25: integer which is more useful.
Creating a Debugging FunctionAlthough using the above echo() statement does what we want, it's a chore if you have to keep typing:
echo "\$testValue : $testvalue : " . gettype($testValue) . " <br> "; at various points in your code to check the value of variables. To make things easier, we're going to create a function, into which we'll add our code:
<?php function debuginfo($param1, $param2) { echo "\$$param2 : $param1 : " . gettype($param1) . "<br>"; } ?> We can now call this function in our code using:
debuginfo($string, "stringname"); So if we have a variable called $teststring, you can call the function as follows:
debuginfo($teststring,"teststring"); This is much easier and quicker to type. The output for $teststring is: $teststring : Hello World: string Next, we'll start adding to the function to make it more useful.
Creating a Global Debug OptionIt's useful to be able to leave your debug function calls in your code on a permanent basis, and it's even worth going so far as to add them as you're creating the page. However, we don't want the debug functions to show when the page is normal use, so we are going to add a switch so we can turn the function on and off, as appropriate. We are going to use the variable $debug as our switch, and it can be set to true or false. Adding this to our function gives the following code:
<?php function debuginfo($param1, $param2) { global $debug; if ($debug == true) echo "\$$param2 : $param1 : " . gettype($param1) . "<br>"; } ?> We can now set $debug on our page once, and it will apply to every use of the debuginfo function. Normally, variables in the main script cannot be used inside functions. Declaring $debug as global means that it can be seen from within the function, even though it is declared outside of the function. To turn our function on, we use:
$debug = true; To turn it off, we use:
$debug = false; We can now activate or de-activate the debuginfo() function by setting the one variable. If you don't declare or set the variable $debug in your main script, then by default the debuginfo() function is turned off. To set up the script so that you can quickly turn on the debuginfo() function using the page URL, add the following code:
$debug = $HTTP_GET_VARS['debug']; if your normal page URL is: http://www.mywebsite.com/testpage.php You can turn on the debuginfo() function by using the URL: http://www.mywebsite.com/testpage.php?debug=true This only works if $debug is not set to false in your main script. It's very useful however, as it allows you to turn on debugging and check the status of your page, without having to make a change to the code and uploading the page again.
Adding Array Support Into the debuginfo() FunctionNext we're going to add to the debuginfo() function, so that it can handle arrays which are passed to it. The new code is shown below:
<?php function debuginfo($param1, $param2, $param3){ global $debug; if ($debug == true){ if (gettype($param1) == "array") { if (count($param1) > 0 ) { echo " <table width='200' border='1' cellspacing='0' cellpadding='0'> <tr> <td> <table width='100%' border='0' cellspacing='2' cellpadding='2'> <tr> <td><b> \$$param2 </b></td> <td><b> line: $param3 </b></td> </tr> "; foreach($param1 as $key => $value){ echo " <tr> <td> $key </td> <td> $value </td> </tr> "; } echo " </table> </td> </tr> </table> "; } } else { echo "\$$param2 : $param1 : " . gettype($param1) . " line number: $param3<br>"; } } } ?> First of all, we've added an extra parameter, $param3, which is going to hold the line number that the variable occurs on. We can now access the debuginfo() function with:
debuginfo($variable, "variable name", line number); We've also added a test to see if the variable that is passed to the function is an array, using the PHP gettype() function. We next check that the array isn't empty, in which case we ignore it by using the PHP count() function, which counts the number of elements in an array. We then send out some HTML code to create a table in which we can show the element keys and values. Look at the block of code that writes out the array's element details:
foreach($param1 as $key => $value){ echo " <tr> <td>$key</td> <td>$value</td> </tr>"; We use foreach to loop through each element of the array, creating a new table row for each line. This means that the code creates as many table rows as necessary to show the array's elements.
Creating a Debugging Include FileTo tidy our code further, we are going to move our debugging function into a separate include file. Open a blank page, and cut and paste the debuginfo() function (including the PHP tags <?php and ?> ), into the new page. Save the new page as include/debug_helper.php. So now we have the debuginfo() function in an include file, all we need is the following code to load our include file, and then set the debug status:
<?php include_once("../include/debug_helper.php"); ?> <?php $debug = true; ?> This code can be inserted onto any page to make the debuginfo() function available. We've used the PHP function include_once() as it's a good habit to get into. Errors can be caused by loading in an include file more than once, which could happen on a page with a lot of code and a lot of include files. As its name suggests, include_once() ensures this doesn't happen and makes sure each include file is opened once by the page, so should be used in preference to the ordinary PHP include() function.
debuginfo() in ActionNext we're going to show debuginfo() in action, by creating a simple form consisting of 3 fields: name, age, and level. The code for the whole page is shown below:
<?php include_once("../include/debug_helper.php"); ?> <?php $debug = true; ?> <html> <head> <title>Using the debuginfo function</title> </head> <body> <form name="form1" method="post" action="<?php echo "$PHP_SELF" ?>"> <table width="25%" border="0"> <tr> <td>name:</td> <td> <input name="name" type="text" ></td> </tr> <tr> <td>age:</td> <td> <input name="age" type="text" ></td> </tr> <tr> <td>level:</td> <td> <select name="select"> <option value="1" selected>Level 1</option> <option value="2">Level 2</option> <option value="3">Level 3</option> <option value="4">Level 4</option> </select> </td> </tr> <tr> <td> </td> <td> <input type="submit" name="Submit" value="Submit"></td> </tr> </table> </form> <?php debuginfo($HTTP_POST_VARS, "formdata", 42); ?> </body> </html> First we start with a blank HTML page. Add the following code above the <HTML> tag:
<?php include_once("../include/debug_helper.php"); ?> <?php $debug = true; ?> We then create a simple form with the three fields above, and set it to submit back to itself using:
<?php echo "$PHP_SELF"; ?> for the form action. This automatically inserts the name and path of the current page when the script is run. Below the form we added the following PHP code:
<?php debuginfo($HTTP_POST_VARS, "formdata", 42); ?> $HTTP_POST_VARS is the array we're sending to the debuginfo() function, formdata is the reference name we're giving the data and 42 is the line number the debuginfo() function is on. Next we upload the new page to the server and load it in a browser. We then enter some test data, and submit the form, which gives the following result.
As you can see the debuginfo() function prints the form field names and values in a nicely formatted table.
Expanding debuginfo() FurtherAlthough we used a very simple example to show debuginfo() in action, it can be extremely useful, and can help you see the variables during the script execution, so you can quickly spot errors. debuginfo() is still quite simple, and there are many ways it could be expanded further, such as adding code to log the variables to a text file, instead of printing them to the screen, or only showing certain variable types, etc. After a while, you'll soon have an ever-expanding debugging facility, to help keep your pages error free.
Two Brains Are Better Than OneIt's often harder to spot errors in your own code, as opposed to another programmer's, as you know how the code is supposed to function, and it can be hard to see past this, and to see what the code is actually doing. If you have a friend or colleague who also programs in PHP, it can be a good idea to swap code with errors. Not only can someone else probably spot the errors quicker than you can, but they can also give their opinion and suggest ideas you may not have thought of.
SQL ErrorsErrors in your SQL can be resolved more easily if you print your SQL query to the screen, again by using the echo() function. This way ensures you can see the actual query that's being sent to the MySQL server, including the parts of the query that are dynamic and change at runtime. If you're building a complex SQL query, it can be best to build it in segments, starting with a basic query and then testing that, and then adding extra parts to the query, testing after each part, until the final query is completed. This way is quicker and easier than trying to debug a complex query.
Where To Seek HelpIf you get totally stuck with an error, or have any questions about PHP, there are a number of excellent resources available on the Internet which can help you.
Macromedia ForumsThe Macromedia forums should really be your first port of call, if you have any questions or problems when using Dreamweaver MX. They contain a large number of friendly, helpful people, who are more than likely to be able to help you. Just searching through the appropriate groups can give you quick answers to your questions. The forums are available through your browser on the web, or through your newsreader. There are groups for each Macromedia program, as well as subgroups in some cases, and they are "staffed" by Macromedia users, and also members of the Team Macromedia program, so you're sure to find the help you need. Full details and addresses for the forums can be found at the Macromedia web site at http://www.macromedia.com/.
Web SitesThere are a large number of PHP-related web sites on the Internet, with new ones frequently appearing:
NewsgroupsThere are also a number of newsgroups dedicated to PHP. Newsgroups are a lot faster moving, and messages are posted 24 hours a day. As a result, posting your question to one of the PHP groups can get you a much quicker response, and faster answers to your questions.
Another useful resource is the experimental front end for all of the PHP mailing lists, which can be found at: http://news.php.net/. |