Lesson Tuesday

Lesson Goals

  • Learn some techniques for debugging in any language
  • Learn some techniques for fixing errors in your PHP apps.

Learn to love your errors

PHP is an "exception-light" language, meaning that unless it encounters something that stops it in its tracks, your program will run. Sounds nice at first, but this can mean that more subtle errors don't show up immediately, until they have become bigger problems.

From "phptherightway.com":

"PHP has several levels of error severity. The three most common types of messages are errors, notices and warnings: EERROR, ENOTICE, and E_WARNING. Errors are fatal run-time errors and are usually caused by faults in your code and need to be fixed as they’ll cause PHP to stop executing. Notices are advisory messages caused by code that may or may not cause problems during the execution of the script, execution is not halted. Warnings are non-fatal errors, execution of the script will not be halted."

Normally, you only see the most severe errors, so it can be helpful to tell PHP to display every error, notice and warning to get more clues about things that could be wrong in your code. This way you can catch bugs before they get too difficult.

Errors are there to give you clues. They will almost certainly not tell you exactly what's wrong with your code, but they will point you in the right direction. Look for things like a line number which made the program stop, or key words that you recognize from your code.

Your first step in debugging should be to follow the errors: go look at that line number, and the ones surrounding to see if you can track down your problem. Ask yourself "Does this look right?" So much of programming is about pattern recognition - which is why stylistic things like indentation are important. If you get used to the way clean code looks, and more of your mistakes will be visually obvious and easier to debug.

What if I have no errors? MY SCREEN IS BLANK!

First of all, don't panic. That's another good debugging technique. Accept that encountering bugs is just part of programming, and you WILL figure them out eventually. Hitting a snag where you don't have errors, but your program still isn't working, can be tricky. Here are some ways to deal with this problem.

Debugging in Silex

If you hit the BSOD (blank screen of death) in a Silex app, add these lines to your app.php file right under your require_once statements.

//Add symfony debug component and turn it on.
use Symfony\Component\Debug\Debug;
Debug::enable();

// Initialize application
$app = new Silex\Application();

// Set Silex debug mode in $app object
$app['debug'] = true;

These lines of code will make sure that you get detailed error messages in the browser if something goes wrong.

Note: You should not add a second copy of the $app = new Silex\Application(); line. That line is only included above because you have to make sure to write this line: $app['debug'] = true; after the $app is created. You can't have a line of code using $app unless you have set $app equal to an instance of Silex\Application.

Using echo and var_dump()

One of the easiest ways to find out what the value of a variable is in PHP is to use the echo keyword. This will print out the value of a variable at the top of your browser if you have a server running. For example:

foreach ($input_array_of_words as $word) {
    array_push($output_titlecased, ucfirst($word));
    echo ucfirst($word."~");
}

This would print out Cat~Bat~ if the $input_array_of_words variable contained the strings "cat" and "bat".

Another useful debugging tool is var_dump(), which works by displaying the structure and content of arrays and objects. Here is how to use var_dump() in either your Silex app.php file or your class declaration.

$ages = array('Jane' => 7, 'Jackie' => 4, 'Bob' => 5 , 'Burt' = 9);
var_dump($ages);

This array of children's ages will print to the top of your browser with this information:

array(4) { ["Jane"]=> int(7) ["Jackie"]=> int(4) ["Bob"]=> int(5) ["Burt"]=> int(9) }

Here is a screenshot: A screenshot of the example using var_dump

It will also inform you if something is an integer, a string, an array, etc and label how many characters are in your strings or how many objects are in an array.

Debugging techniques that work in any language: document your work!

It's easy to get lost when you're debugging if you don't keep track of what you've tried already.

As you work on debugging something, write down each thing you try and what the result is. This lets you keep track of the clues you find as you narrow down your problem. This will also make it a lot easier to explain your problem to someone else. Other developers will really appreciate it, if they can see an exact list of what you've tried so far like: "I know that the problem is not here, because I tried this. I thought the problem might be this, but I have eliminated that possibility by deleting these lines of code..." etc. Organization is key - you don't want to be running in circles trying the same things over and over again.

Comment out until it works. Add until it breaks.

Another good way to diagnose what's wrong with your code is to debug by section. Comment out everything (the keyboard command for this is Command / on a Mac) until you can make the most basic step in your code work. Commenting out tells your program to ignore the code until you uncomment it. If you want your page to look cleaner, you can copy any code you are commenting out into a blank file first, save it somewhere else, and be able to start from a clean slate.

Try just displaying "hello" on your screen. Then slowly add your code back in, build it back up one piece at a time, until you find out what caused it to break. Or you can comment out a section of the code at a time and see if the program works or not. That way you can narrow down where the bug in your code is.

Also, since you are regularly making commits to Git as you work (make sure you are doing that!!) you can always go back to a previous revision if you want to see what has changed, or recover work that you have deleted. You can see your previous revisions on Github by clicking on "commits" in the top left corner of your repo, or you can actually revert your code to a previous commit by running $ git log, finding the commit number of the version you want to revert to and then running $ git reset and adding the commit number at the end. For example $ git reset 56e05fced

Googling

Google is a fantastic tool, but it should be used with caution. If you can't see the problem in your code, definitely google your error messages. Look at message boards like Stack Overflow to see if anyone else has encountered your problem, but before you use someone else's code, make sure that you understand exactly what it is doing. Blindly copying and pasting someone else's code into yours and then using it because "it just works for some reason" is going to create a headache for you later. Guaranteed.

Don't get mad

This might seem like a no brainer, but sometimes you just need to relax. If you have been banging your head against a problem long enough that you are getting angry at it, take a deep breath and walk away for a little while. Sometimes the answer might be right under your nose, but you're frustrated enough that you are not seeing it. You can always take a walk and then come back to it.

One thing at a time

Step through your code line by line from beginning to end, assuming nothing. It can really help to say what each line is doing out loud, or write it down. If there's anything you're unsure of along the way, test it! Print your variables to your screen, or if that doesn't work, make sure you can print a basic word onto the screen. Simplify everything. Check things that you assume are working, even if it seems like they are obviously working or that it would be impossible if they aren't - I like to call that a sanity check. For example, maybe nothing is changing on your screen because you've been editing the wrong copy of your file for two hours because you had one copy of it in Documents and the other one on your Desktop.

Ask a friend

When you're stumped on a problem, ask a friend. Sometimes a totally different pair of eyes might spot something simple, like a spelling error, that you've skipped over. In fact, frequently, just the act of explaining your problem to someone can be enough to make you realize what the solution is.

When you find the solution...

Write it down in your mistake journal! Ask yourself, how will I prevent this problem from happening again? What error message should I watch for? If I see the error again, where should I look to fix it? You want to save yourself time and learn from your mistakes. Embrace your bugs as opportunities to prevent future ones, and understanding why your fix works teaches you deeper concepts about the language.