Printf Debugging in PHP

I've been debugging programs since the 1970's. I have fixed a few bugs over the years! Although nothing beats a symbolic debugger that is able to let me set breakpoints and single step through code, I don't think I'm just being an old dinosaur programmer by saying that "printf" debugging and assertions still have practical uses. That's because most of the time I don't need anything more sophisticated to understand what my code is doing wrong. (I'm more apt to need an IDE-based debugger trying to figure out someone else's code.)

Below is the code snippet that I use to help me do printf debugging in PHP. If you want to use it, place it in an utility file that gets included at the top of your other other PHP files. Of course, using these printing functions will certainly mess up any fancy formatting you may be trying to accomplish on your web page. But inserting an assert() or checkpoint() call in your code is only intended as a quick and easy way to probe buggy behavior anyway.

I would be remiss not to mention that during development (only!), make sure that the Apache web server's php.ini configuration file has set the display_errors parameter to on. I usually catch more than half my PHP scripting bugs this way. Very in-your-face, quick and easy debugging. An alternative to editing the PHP configuration file is to open up a (Ubuntu) terminal window and enter:

    tail -f /var/log/apache2/error.log

This will display the ten latest PHP errors that have been generated.

Here is the code:

// ***************************************************************************
// Development Debugging Utilities.
// (For those of us who like to debug with printing to output and/or log 
// files.)
//
// Note debugging flag below so we don't have to worry too much about leaving
// embedded debugging/assertion dev/test code in source.
//
// Typical Usages:
//
//   assert("$sanity_state == 'SANE' /* This comment will be visible too! */");
//
//   checkpoint(); // Will print 'GOT HERE!' and checkpoint's location
//   checkpoint($var); // Will print $var object and checkpoint's location
//   checkpoint($var, $tag); // Will print $tag string and $var object and 
//                           // checkpoint's location
//
// ***************************************************************************
$DEBUGGING_FLAG = true; // set to false to turn these utilities off!

// Setup for assertions:
assert_options(ASSERT_ACTIVE, $DEBUGGING_FLAG);
if (assert_options(ASSERT_ACTIVE)) {
    error_reporting(E_ALL | E_NOTICE);
}
assert_options(ASSERT_WARNING, true);
assert_options(ASSERT_QUIET_EVAL, true);
function assert_handler($file, $line, $code) {
    echo "<hr><p>
    <b>Assert Triggered</b><br>
    Trigger Code: $code<br>
       &nbspFile: $file<br>
       &nbspLine: $line<br>
    </p><hr>";
}
assert_options(ASSERT_CALLBACK, 'assert_handler');

// Setup for embedded (in the output) checkpoints:
function checkpoint($var='GOT HERE!', $id='CHECKPOINT') {
    global $DEBUGGING_FLAG;
    if ($DEBUGGING_FLAG) {
        $btr = debug_backtrace();
        $line = $btr[0]['line'];
        $file = $btr[0]['file'];
        echo "<hr><p>";
        echo "<b>Checkpoint:</b> $id<br>";
        echo "File: $file<br>";
        echo "Line: $line<br>";
        if (is_array($var)) {
            echo "Value:\n<pre>";
            print_r($var);
            echo "</pre>";
        } elseif(is_object($var)) {
            echo "Value:\n<pre>";
            var_dump($var);
            echo "</pre>";
        } elseif (isset($var)) {
            echo "Value: $var";
        }
        echo "</p><hr>";
    }
}

// Setup for logging errors to the server's log file:
function log_error($msg) {
    global $DEBUGGING_FLAG;
    if ($DEBUGGING_FLAG) {
        $dbg_btr = debug_backtrace();
        $line = $dbg_btr[0]['line'];
        $file = $dbg_btr[0]['file'];
        error_log("function log_error::\"$msg\"::$file::$line");
    }
}

No comments:

Post a Comment