 |
debug_backtrace (PHP 4 >= 4.3.0, PHP 5) debug_backtrace -- Generates a backtrace 说明array debug_backtrace ( void )
debug_backtrace() generates a PHP backtrace.
返回值
Returns an associative array. The possible returned elements
are as follows:
表格 1. Possible returned elements from debug_backtrace() Name | Type | Description |
---|
function | string |
The current function name. See also
__FUNCTION__.
| line | integer |
The current line number. See also
__LINE__.
| file | string |
The current file name. See also
__FILE__.
| class | string |
The current class name. See also
__CLASS__
| type | string |
The current call type. If a method call, "->" is returned. If a static
method call, "::" is returned. If a function call, nothing is returned.
| args | array |
If inside a function, this lists the functions arguments. If
inside an included file, this lists the included file name(s).
|
范例
例子 1. debug_backtrace() example
<?php // filename: a.php
function a_test($str) { echo "\nHi: $str"; var_dump(debug_backtrace()); }
a_test('friend'); ?>
<?php // filename: b.php include_once '/tmp/a.php'; ?>
|
Results similar to the following when executing
/tmp/b.php:
Hi: friend
array(2) {
[0]=>
array(4) {
["file"] => string(10) "/tmp/a.php"
["line"] => int(10)
["function"] => string(6) "a_test"
["args"]=>
array(1) {
[0] => &string(6) "friend"
}
}
[1]=>
array(4) {
["file"] => string(10) "/tmp/b.php"
["line"] => int(2)
["args"] =>
array(1) {
[0] => string(10) "/tmp/a.php"
}
["function"] => string(12) "include_once"
}
} |
|
tiwen at rpgame dot de
01-May-2006 04:25
Another debug output. This is a short function that does not display the args (sometimes password are in arguments ...) and shows the callstack clearly in a table. In most cases i don't need more ...
<?php
function dieDebug($sError)
{
echo "<hr /><div>".$sError."<br /><table border='1'>";
$sOut=""; $aCallstack=debug_backtrace();
echo "<thead><tr><th>file</th><th>line</th><th>function</th>".
"</tr></thead>";
foreach($aCallstack as $aCall)
{
if (!isset($aCall['file'])) $aCall['file'] = '[PHP Kernel]';
if (!isset($aCall['line'])) $aCall['line'] = '';
echo "<tr><td>{$aCall["file"]}</td><td>{$aCall["line"]}</td>".
"<td>{$aCall["function"]}</td></tr>";
}
echo "</table></div><hr /></p>";
die();
}
?>
To use it, simply do something like this:
<?php
if(...) dieDebug("another error found!");
?>
http://synergy8.com
14-Dec-2005 02:37
It should be noted that if an internal php function such as call_user_func in the backtrace, the 'file' and 'line' entries will not be set.
Most debug tracers will use these entries. You should place a check to see if the key exists in the array before using this function. Otherwise notices will be generated.
<?php
$arrTrace = debug_backtrace();
foreach ($arrTrace as $arr)
{
if (!isset ($arr['file']))
{
$arr['file'] = '[PHP Kernel]';
}
if (!isset ($arr['line']))
{
$arr['line'] = '';
}
// Do something
}
?>
tb
22-Jul-2005 02:18
I use this for debugging in my object oriented systems. It allows me to output a debug/error/warning function with exact information about the location that the error was thrown, which is useful. Check it:
<?php
abstract class Debugger {
/**
* Throw a debug message.
*/
abstract function debug($msg);
/**
* Throw an error message.
*/
abstract function error($msg);
/**
* Throw a warning message.
*/
abstract function warning($msg);
/**
* Wrap a message with information about class, function, file and line
* number and return it.
*/
protected function getMsg($msg) {
$bt = debug_backtrace();
// get class, function called by caller of caller of caller
$class = $bt[2]['class'];
$function = $bt[2]['function'];
// get file, line where call to caller of caller was made
$file = $bt[1]['file'];
$line = $bt[1]['line'];
// build & return the message
return "$class::$function: $msg in $file at $line";
}
}
?>
Implement different debuggers for different scenarios (development, testing, production). Each debugger extends Debugger; each of its methods (debug/error/warning) calls $this->getMsg($msg) to get a message with class, function, file, and line information. Then it can either log it, email it, die with it, etc.
Then, just give each object (perhaps using a common superclass Object) a concrete debugger. Then, from any object method, do something like:
<?php
class Foo extends Object {
function bar() {
$this->debugger->error("This is an error");
}
}
?>
Which produces something like:
Foo::bar: This is an error in /some/file at X
diz at ysagoon dot com
24-Nov-2004 06:35
Ok as spagmoid already said, I just realized that my function has a similar bug than jlim's function.
So just add the following line:
if (is_array($bt['args']))
before line:
foreach ($bt['args'] as $a) {
This way you avoid the warning from being displayed.
diz at ysagoon dot com
24-Nov-2004 06:40
And here are my two cents for a useful and good looking backtrace function.
<?php
function backtrace()
{
$output = "<div style='text-align: left; font-family: monospace;'>\n";
$output .= "<b>Backtrace:</b><br />\n";
$backtrace = debug_backtrace();
foreach ($backtrace as $bt) {
$args = '';
foreach ($bt['args'] as $a) {
if (!empty($args)) {
$args .= ', ';
}
switch (gettype($a)) {
case 'integer':
case 'double':
$args .= $a;
break;
case 'string':
$a = htmlspecialchars(substr($a, 0, 64)).((strlen($a) > 64) ? '...' : '');
$args .= "\"$a\"";
break;
case 'array':
$args .= 'Array('.count($a).')';
break;
case 'object':
$args .= 'Object('.get_class($a).')';
break;
case 'resource':
$args .= 'Resource('.strstr($a, '#').')';
break;
case 'boolean':
$args .= $a ? 'True' : 'False';
break;
case 'NULL':
$args .= 'Null';
break;
default:
$args .= 'Unknown';
}
}
$output .= "<br />\n";
$output .= "<b>file:</b> {$bt['line']} - {$bt['file']}<br />\n";
$output .= "<b>call:</b> {$bt['class']}{$bt['type']}{$bt['function']}($args)<br />\n";
}
$output .= "</div>\n";
return $output;
}
?>
And here's a sample of how the output looks like (the last call is on the top):
Backtrace:
file: 56 - /tmp/test.php
call: backtrace()
file: 53 - /tmp/test.php
call: test->bar(15.4, Array(4))
file: 61 - /tmp/test.php
call: test->test("making new object", True)
file: 65 - /tmp/test.php
call: foo(Resource(#2), Null)
ad-rotator.com
01-May-2004 12:11
To simply print out the file/function trace (chain of calls, file and line number before the error):
function getTrace() {
$vDebug = debug_backtrace();
$vFiles = array();
for ($i=0;$i<count($vDebug);$i++) {
// skip the first one, since it's always this func
if ($i==0) { continue; }
$aFile = $vDebug[$i];
$vFiles[] = '('.basename($aFile['file']).':'.$aFile['line'].')';
} // for
$vTraceStr = implode(',',$vFiles);
}
spagmoid at yahoo dot NOSPAMcom
10-Dec-2003 03:47
ATTN: jlim#natsoft.com.my
Great function, but you have a few bugs.
At the line:
foreach($arr['args'] as $v)
Change it to:
$args = array();
if(!empty($arr['args'])) foreach($arr['args'] as $v)
And since line & file are not present in the array if calling from the error handler,
$Line = (isset($arr['line'])? $arr['line'] : "unknown");
$File = (isset($arr['file'])? $arr['file'] : "unknown");
and substitute accordingly.
Here's my version of it, alas with different formatting:
----------------------------------------
function DBG_GetBacktrace()
{
$s = '';
$MAXSTRLEN = 64;
$s = '<pre align=left>';
$traceArr = debug_backtrace();
array_shift($traceArr);
$tabs = sizeof($traceArr)-1;
foreach($traceArr as $arr)
{
for ($i=0; $i < $tabs; $i++) $s .= ' ';
$tabs -= 1;
$s .= '<font face="Courier New,Courier">';
if (isset($arr['class'])) $s .= $arr['class'].'.';
$args = array();
if(!empty($arr['args'])) foreach($arr['args'] as $v)
{
if (is_null($v)) $args[] = 'null';
else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
else if (is_object($v)) $args[] = 'Object:'.get_class($v);
else if (is_bool($v)) $args[] = $v ? 'true' : 'false';
else
{
$v = (string) @$v;
$str = htmlspecialchars(substr($v,0,$MAXSTRLEN));
if (strlen($v) > $MAXSTRLEN) $str .= '...';
$args[] = "\"".$str."\"";
}
}
$s .= $arr['function'].'('.implode(', ',$args).')</font>';
$Line = (isset($arr['line'])? $arr['line'] : "unknown");
$File = (isset($arr['file'])? $arr['file'] : "unknown");
$s .= sprintf("<font color=#808080 size=-1> # line %4d, file: <a href=\"file:/%s\">%s</a></font>",
$Line, $File, $File);
$s .= "\n";
}
$s .= '</pre>';
return $s;
}
Fabian dot Kraetzer at gmx dot de
01-Sep-2003 09:18
I coded a function, too. Just call debug() evertime you think you could encounter an error:
<?
function debug()
{
$debug_array = debug_backtrace();
$counter = count($debug_array);
for($tmp_counter = 0; $tmp_counter != $counter; ++$tmp_counter)
{
?>
<table width="558" height="116" border="1" cellpadding="0" cellspacing="0" bordercolor="#000000">
<tr>
<td height="38" bgcolor="#D6D7FC"><font color="#000000">function <font color="#FF3300"><?
echo($debug_array[$tmp_counter]["function"]);?>(</font> <font color="#2020F0"><?
//count how many args a there
$args_counter = count($debug_array[$tmp_counter]["args"]);
//print them
for($tmp_args_counter = 0; $tmp_args_counter != $args_counter; ++$tmp_args_counter)
{
echo($debug_array[$tmp_counter]["args"][$tmp_args_counter]);
if(($tmp_args_counter + 1) != $args_counter)
{
echo(", ");
}
else
{
echo(" ");
}
}
?></font><font color="#FF3300">)</font></font></td>
</tr>
<tr>
<td bgcolor="#5F72FA"><font color="#FFFFFF">{</font><br>
<font color="#FFFFFF"> file: <?
echo($debug_array[$tmp_counter]["file"]);?></font><br>
<font color="#FFFFFF"> line: <?
echo($debug_array[$tmp_counter]["line"]);?></font><br>
<font color="#FFFFFF">}</font></td>
</tr>
</table>
<?
if(($tmp_counter + 1) != $counter)
{
echo("<br>was called by:<br>");
}
}
exit();
}
?>
bernyregeling AT hotmail DOT com
08-Aug-2003 07:29
I wrote this function, in addition to jlim, for a nice NO-HTML output.
Thee result has similarities to a Java-error. Hope you like it.
(BTW, this function exits the script too, if debug_backtrace is displayed)
------------------------------
function debug_bt()
{
if(!function_exists('debug_backtrace'))
{
echo 'function debug_backtrace does not exists'."\r\n";
return;
}
//echo '<pre>';
echo "\r\n".'----------------'."\r\n";
echo 'Debug backtrace:'."\r\n";
echo '----------------'."\r\n";
foreach(debug_backtrace() as $t)
{
echo "\t" . '@ ';
if(isset($t['file'])) echo basename($t['file']) . ':' . $t['line'];
else
{
// if file was not set, I assumed the functioncall
// was from PHP compiled source (ie XML-callbacks).
echo '<PHP inner-code>';
}
echo ' -- ';
if(isset($t['class'])) echo $t['class'] . $t['type'];
echo $t['function'];
if(isset($t['args']) && sizeof($t['args']) > 0) echo '(...)';
else echo '()';
echo "\r\n";
}
//echo '</pre>';
exit;
}
jlim#natsoft.com.my
13-Mar-2003 09:51
Pretty print the backtrace(). Functions are indented based on call value, and file is linked using file:// for convenience.
Enjoy, John Lim
function adodb_backtrace($print=true)
{
$s = '';
if (PHPVERSION() >= 4.3) {
$MAXSTRLEN = 64;
$s = '<pre align=left>';
$traceArr = debug_backtrace();
array_shift($traceArr);
$tabs = sizeof($traceArr)-1;
foreach ($traceArr as $arr) {
for ($i=0; $i < $tabs; $i++) $s .= ' ';
$tabs -= 1;
$s .= '<font face="Courier New,Courier">';
if (isset($arr['class'])) $s .= $arr['class'].'.';
foreach($arr['args'] as $v) {
if (is_null($v)) $args[] = 'null';
else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
else if (is_object($v)) $args[] = 'Object:'.get_class($v);
else if (is_bool($v)) $args[] = $v ? 'true' : 'false';
else {
$v = (string) @$v;
$str = htmlspecialchars(substr($v,0,$MAXSTRLEN));
if (strlen($v) > $MAXSTRLEN) $str .= '...';
$args[] = $str;
}
}
$s .= $arr['function'].'('.implode(', ',$args).')';
$s .= sprintf("</font><font color=#808080 size=-1> # line %4d,".
" file: <a href=\"file:/%s\">%s</a></font>",
$arr['line'],$arr['file'],$arr['file']);
$s .= "\n";
}
$s .= '</pre>';
if ($print) print $s;
}
return $s;
}
|  |