PHP Error Handling
Printing a Stack Trace
Problem
You want to know what’s happening at a specific point in your program, and what happened leading up to that point.
Solution
Use debug_print_backtrace():
function stooges() {
print "woo woo woo!\n";
larry();
}
function larry() {
curly();
}
function curly() {
moe();
}
function moe() {
debug_print_backtrace();
}
stooges();
This will print:
woo woo woo!
#0 moe() called at [backtrace.php:12]
#1 curly() called at [backtrace.php:8]
#2 larry() called at [backtrace.php:4]
#3 stooges() called at [backtrace.php:19]
Discussion
The handy debug_print_backtrace() function allows you to quickly get a sense of what has been been going on in your application immediately before you called a particular function.
The more complicated your application, the more information you can expect to have returned from the backtrace functions. For debugging larger codebases, you may achieve bug-hunting success more quickly using a full debugging extension, such as Xdebug, or an integrated development environment (IDE), such as NetBeans, that supports setting breakpoints, stepping in and out of blocks of code, watching the evolution of variables, and more.
If all you need is a little more information than you can get from sprinkling print 'Here I am on line ' . LINE; statements throughout your code, debug_print_back trace() will suit your needs well.
The output from debug_print_backtrace() includes, by default, the arguments passed to each function. If those arguments are big arrays or complicated objects, it can make the output unwieldy. You can pass the constant DEBUG_BACKTRACE_IGNORE_ARGS as a first argument to debug_print_backtrace() to have arguments eliminated from the output. If you only need to keep track of the sequence of functions called, this is perfect.
A companion to debug_print_backtrace() is debug_backtrace(). Instead of outputting the backtrace, debug_backtrace() returns it as an array, one element per stack frame. This is useful if you only need to print certain elements of the backtrace, or you want to manipulate it programmatically.
Example Using debug_backtrace()
function print_parsed_backtrace() {
$backtrace = debug_backtrace();
for ($i = 1, $j = count($backtrace); $i < $j; $i++) {
$frame = $backtrace[$i];
if (isset($frame['class'])) {
$function = $frame['class'] . $frame['type'] . $frame['function'];
} else {
$function = $frame['function'];
}
print $function . '()';
if ($i != ($j - 1)) {
print ', ';
}
}
}
function stooges() {
print "woo woo woo!\n";
Fine::larry();
}
class Fine {
static function larry() {
$brothers = new Howard;
$brothers->curly();
}
}
class Howard {
function curly() {
$this->moe();
}
function moe() {
print_parsed_backtrace();
}
}
stooges();
This prints:
woo woo woo!
Howard->moe(), Howard->curly(), Fine::larry(), stooges()
Example causes a chain of functions to be invoked, with one of them calling print_parsed_backtrace(). This function then gets information about the stack frames from debug_backtrace() and then walks through them. The for() loop starts at 1, not 0, because the first frame on the stack (array element 0) is for the call to print_parsed_backtrace() itself. If the stack frame is a method call, then the class element of the array contains the class name of the method and the type element contains :: for a static method call and -> for an instance method call. If there’s no class element, it’s just a regular function call.
No comments:
Post a Comment