dpDebug2
about | details | demos | download

debugging php

Have you ever spent time tracking down a problem with your PHP code that causes it to give unexpected results? Have you ever wished for a quick and easy way to visualise exactly what's going on, where and why? Of course you have. I have, too. That's why I made dpDebug: a single-file PHP library that 'injects' a handy pop-up list of messages defined by you into any page you like. All you need to do is call the deb() function at each step you want to trace, with a brief description of what's happening, and it'll be added to the dpDebug message log. You can even specify message levels (fatal, warning, notice, info, trivial, highlight or custom) and set a verbosity level to choose how much detail you want to see in the log.

Of course, dpDebug isn't meant to be active on a live website. It's easy to enable or disable depending on whichever circumstances you like:

Example: selectively enabling dpDebug

<?php
 
include("dpDebug2.php");
 if (
$dev_mode) {
     
set_verbosity(10);
 } else {
     
set_verbosity(0);
 }
?>

Of course, the conditions for enabling dpDebug are entirely up to you. I usually use a cookie containing a hash, set by a password-protected enable_debug.php:

Example: using a cookie to enable dpDebug

<?php
 
include("dpDebug2.php");
 
$verbosity 0;
 if (isset(
$_COOKIES['dpDebug_hash'])){
      if (
$_COOKIES['dpDebug_hash'] == md5("my dpDebug passphrase/seed" $_SERVER["REMOTE_ADDR"])) $verbosity 10;
 }
 
set_verbosity($verbosity);
 
?>

the deb() function

deb(string Message [ , int Level [ , string Label [ , bool Code [ , array Trace ] ] ] ]);

The deb() function is the main interface between the programmer and dpDebug. It appends a message to the debug log, so you'll want to call this wherever something's happening that you'll want to monitor when a problem arises.

It sounds like a chore to be adding deb() calls all over the place. The few people who were aware of dpDebug 1 agreed, however, that it quickly became habit, and that it was very much worth it for the huge boost they gained in productivity and potential of complexity. If you have a lot of existing code for which it would make little sense to trawl through, adding calls to deb() everywhere it might be useful, you'll probably find yourself adding it here and there to start with, then eventually ending up with a detailed record of what's happening. Just try it: you might never go back! Even if you don't make regular calls to deb(), you will still find dpDebug a handy way to show and track PHP errors without breaking the flow of your page.

Example: basic use of the deb() function

<?php
 
include("dpDebug2.php");
 
deb("Loading configuration",4); // level 4 (info) message
 
require("includes/config.php");
  
 if (
$config['admin_password'] == "secret"deb("You are using the default admin password",2); // level 2 (warning) message
  
 
mysql_connect($config['db_host'], $config['db_user'], $config['db_password']) or deb("Couldn't connect to MySQL server",1); // level 1 (fatal) message
?>

You will have noticed that this would call deb() with a level 1 (fatal) message when our script fails to connect to a MySQL server. As well as appending the message to the debug log, calling deb() with a Level argument of 1 results in an extra one of two things, depending on the verbosity level set with set_verbosity():

Either way, you'll see, calling deb() with a Level argument of 1 will stop the script. This makes deb(s , 1) a great alternative to using die() or trigger_error() to handle your feedback when things are looking fubar.

deb()'s Level parameter indicates the importance of the message. It affects the colour scheme in which the message appears in the log, as well as whether it should be shown depending on the verbosity level set with set_verbosity(). The default value for Level is 4 (info).

dpDebug message levels

1: Fatal (halts execution)
2: Warning
3: Notice
4: Info
5: Trivial
6: Highlight
>6: Custom levels (no colour scheme)

The Label parameter, if set, overrides the message's label which appears to the left of the message in the queue. This can be handy to categorise the messages more specifically.

The boolean Code parameter specifies whether the debug message should be surrounded by <code> tags. Default is false

More information and other uses for deb() can be found in the details page.

more on set_verbosity()

Because each debug message has an associated debug level, you can specify an importance threshold to determine which messages to display. Sometimes you won't want loads of trivial messages shown in the debug panel, but will want to see any warnings. Setting the verbosity level with set_verbosity(int Level) makes sure only messages with that level or lower (that is, more important) are displayed. set_verbosity() affects debug messages retrospectively. verbosity.php on the demo page tests and demonstrates this.

tracing calls

dpDebug 2 can display the chain of function calls associated with each debug message. While this is possibly the most useful feature of dpDebug, callstack display must be enabled explicitly for security reasons: to make sure nobody uses it on a live site without understanding the security basics. To enable callstack display, simply call deb_callstack(true). Likewise, to disable it just call deb_callstack(false). When the callstack is enabled, moving your mouse over the filename and line appended to each debug message will display a tooltip with the chain of calls that resulted in deb() being called. A list of calls will also be shown on the dpDebug error page if a call to deb() is made with a Level argument of 1.