错误处理 函数
在线手册:中文 英文
PHP手册

debug_print_backtrace

(PHP 5)

debug_print_backtrace Prints a backtrace

说明

void debug_print_backtrace ([ int $options = 0 [, int $limit = 0 ]] )

debug_print_backtrace() prints a PHP backtrace. It prints the function calls, included/required files and eval()ed stuff.

参数

options

As of 5.3.6, this parameter is a bitmask for the following options:

debug_print_backtrace() options
DEBUG_BACKTRACE_IGNORE_ARGS Whether or not to omit the "args" index, and thus all the function/method arguments, to save memory.

limit

As of 5.4.0, this parameter can be used to limit the number of stack frames printed. By default (limit=0) it prints all stack frames.

返回值

没有返回值。

更新日志

版本 说明
5.4.0 Added the optional parameter limit.
5.3.6 Added the optional parameter options.

范例

Example #1 debug_print_backtrace() example

<?php
// include.php file

function a() {
    
b();
}

function 
b() {
    
c();
}

function 
c(){
    
debug_print_backtrace();
}

a();

?>
<?php
// test.php file
// this is the file you should run

include 'include.php';
?>

以上例程的输出类似于:

#0  c() called at [/tmp/include.php:10]
#1  b() called at [/tmp/include.php:6]
#2  a() called at [/tmp/include.php:17]
#3  include(/tmp/include.php) called at [/tmp/test.php:3]

参见


错误处理 函数
在线手册:中文 英文
PHP手册
PHP手册 - N: Prints a backtrace

用户评论:

Sammaye (24-Feb-2011 12:26)

Most methods of getting the backtrace and printing are susceptible to a certain runtime flaw.

If the user is able to produce 100+ errors this will throw an error which in turn will throw 100+ errors on each nest of get_args() creating an infinite loop and eventually downing your server.

If you are looking for a simple backtrace that (so far) will not fall to this error then use this:

<?php
   
foreach(debug_backtrace() as $k=>$v){
        if(
$v['function'] == "include" || $v['function'] == "include_once" || $v['function'] == "require_once" || $v['function'] == "require"){
           
$backtracel .= "#".$k." ".$v['function']."(".$v['args'][0].") called at [".$v['file'].":".$v['line']."]<br />";
        }else{
           
$backtracel .= "#".$k." ".$v['function']."() called at [".$v['file'].":".$v['line']."]<br />";
        }
    }
?>

chris dot kistner at gmail dot com (01-Apr-2010 12:31)

Here's a function that returns a string with the same information shown in debug_print_backtrace(), with the option to exclude a certain amount of traces (by altering the $traces_to_ignore argument).

I've done a couple of tests to ensure that it prints exactly the same information, but I might have missed something.

This solution is a nice workaround to get the debug_print_backtrace() information if you're already using ob_start() in your PHP code.

<?php
function get_debug_print_backtrace($traces_to_ignore = 1){
   
$traces = debug_backtrace();
   
$ret = array();
    foreach(
$traces as $i => $call){
        if (
$i < $traces_to_ignore ) {
            continue;
        }

       
$object = '';
        if (isset(
$call['class'])) {
           
$object = $call['class'].$call['type'];
            if (
is_array($call['args'])) {
                foreach (
$call['args'] as &$arg) {
                   
get_arg($arg);
                }
            }
        }       

       
$ret[] = '#'.str_pad($i - $traces_to_ignore, 3, ' ')
        .
$object.$call['function'].'('.implode(', ', $call['args'])
        .
') called at ['.$call['file'].':'.$call['line'].']';
    }

    return
implode("\n",$ret);
}

function
get_arg(&$arg) {
    if (
is_object($arg)) {
       
$arr = (array)$arg;
       
$args = array();
        foreach(
$arr as $key => $value) {
            if (
strpos($key, chr(0)) !== false) {
               
$key = '';    // Private variable found
           
}
           
$args[] =  '['.$key.'] => '.get_arg($value);
        }

       
$arg = get_class($arg) . ' Object ('.implode(',', $args).')';
    }
}
?>

bishop (28-Jul-2009 09:20)

Another way to manipulate and print a backtrace, without using output buffering:

<?php
// print backtrace, getting rid of repeated absolute path on each file
$e = new Exception();
print_r(str_replace('/path/to/code/', '', $e->getTraceAsString()));
?>

bradley dot giesbrecht at gmail dot com (14-Jan-2009 12:51)

I was using the function by dany dot dylan at gmail dot com and found that preg_replace had string length limits. So here is yet another output format function.

<?php
if ( !function_exists ( "mydie" ) ) {
    function
mydie (  ) { $this_file = __FILE__ ; $this_line = __LINE__ ;
       
$buffer = array (  ) ;
       
$trace_calls = "" ;
       
ob_start (  ) ;
       
debug_print_backtrace (  ) ;
       
$buffer[ "0" ] = ob_get_contents (  ) ;
       
ob_end_clean (  ) ;
       
$buffer[ "0" ] = array_slice ( explode ( "#" , $buffer[ "0" ] ) , 1 , -1 , false ) ;
        foreach (
$buffer[ "0" ] as $key => $value ) {
           
$value = explode ( ") called at [" , $value ) ;
            if (
$key == 0 ) {
               
$value[ "0" ] = "0  " . __FUNCTION__ . "(see above vars)" ;
            }
           
$trace_calls .= "#" . implode ( ")\n\tcalled at [" , $value ) ;
        }
        unset (
$buffer , $key , $value ) ;
        echo
"<pre>function " . __FUNCTION__ . " lives here:{$this_file}:{$this_line}</pre>" ;
        echo (
"<pre>" . print_r( func_get_args (  ) , true ) . "</pre>" ) ;    
        if (
$trace_calls == "" ) $trace_calls = "No functions were called." ;
        echo (
"<pre>" . $trace_calls . "</pre>" ) ;    
        die ;
    }
}
function
a (  ) {
   
b ( func_get_args (  ) , 2 ) ;
}
function
b (  ) {
   
c ( func_get_args (  ) , 3 ) ;
}
function
c (  ) {
   
mydie ( func_get_args (  ) , 4 ) ;
}
a ( 1 ) ;
?>

## outputs
function mydie lives here:/path/file.php:4
Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => Array
                        (
                            [0] => 1
                        )

                    [1] => 2
                )

            [1] => 3
        )

    [1] => 4
)
#0  mydie(see above vars))
    called at [/path/file.php:54]
#1  c(Array ([0] => Array ([0] => 1),[1] => 2), 3)
    called at [/path/file.php:49]
#2  b(Array ([0] => 1), 2)
    called at [/path/file.php:43]

dany dot dylan at gmail dot com (11-Nov-2008 05:51)

I like the output of debug_print_backtrace() but I sometimes want it as a string.

bortuzar's solution to use output buffering is great, but I'd like to factorize that into a function.  Doing that however always results in whatever function name I use appearing at the top of the stack which is redundant.

Below is my noddy (simple) solution.  If you don't care for renumbering the call stack, omit the second preg_replace().

<?php
   
function debug_string_backtrace() {
       
ob_start();
       
debug_print_backtrace();
       
$trace = ob_get_contents();
       
ob_end_clean();

       
// Remove first item from backtrace as it's this function which
        // is redundant.
       
$trace = preg_replace ('/^#0\s+' . __FUNCTION__ . "[^\n]*\n/", '', $trace, 1);

       
// Renumber backtrace items.
       
$trace = preg_replace ('/^#(\d+)/me', '\'#\' . ($1 - 1)', $trace);

        return
$trace;
    }
?>

harmor (19-Feb-2008 09:54)

Input (Using: PHP Version 5.2.5-pl1-gentoo):
<?php
class CTest
{
    public static function
say($a_szVar)
    {
       
debug_print_backtrace();
        echo
'<br />';
    }
}

CTest::say('static call');

$obj = new CTest;
$obj->say('object call');
   
?>

Output:
#0 CTest::say(static call) called at [C:\PHPDocument4.php:11]
#0 CTest::say(object call) called at [C:\PHPDocument4.php:15]

Notice that the second line of the output outputs "::" instead of "->" when calling the function using an object.

taner (21-Aug-2007 12:52)

bortuzar: a simpler version, w/o output buffering:

<?php

$query
= sprintf("INSERT INTO EventLog (Trace) VALUES ('%s')",
   
mysql_real_escape_string(join("\n", debug_backtrace())) );
mysql_query($query);

?>

bortuzar at gmail dot com (05-Jun-2007 07:23)

If you want to get the trace into a variable or DB, I suggest to do the following:

<?php
    ob_start
();
       
debug_print_backtrace();
   
$trace = ob_get_contents();
   
ob_end_clean();

$query = sprintf("INSERT INTO EventLog (Trace) VALUES ('%s')",
           
mysql_real_escape_string($trace));
mysql_query($query);
?>

petermarkellis at googlemail dot com (28-Mar-2007 10:10)

A cleaner example:
<?php
function a() {
  
b();
}

function
b() {
  
c();
}

function
c(){
  
debug_print_backtrace();
}

a();

?>

outputs:
#0  c() called at [C:\debugbacktracetest.php:7]
#1  b() called at [C:\debugbacktracetest.php:3]
#2  a() called at [C:\debugbacktracetest.php:14]

aidan at php dot net (15-Mar-2005 09:47)

This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat