(PHP 5)
debug_print_backtrace — 打印一条回溯。
$options
= 0
[, int $limit
= 0
]] )debug_print_backtrace() 打印了一条 PHP 回溯。它打印了函数调用、被 included/required 的文件和 eval() 的代码。
options
截至 5.3.6,这个参数是以下选项的位掩码:
DEBUG_BACKTRACE_IGNORE_ARGS | 是否忽略 "args" 的索引,包括所有的 function/method 的参数,能够节省内存开销。 |
limit
截至 5.4.0,这个参数能够用于限制返回堆栈帧的数量。
默认为 (limit
=0) ,返回所有的堆栈帧。
没有返回值。
版本 | 说明 |
---|---|
5.4.0 |
添加了可选的参数 limit 。
|
5.3.6 |
添加了可选的参数 options 。
|
Example #1 debug_print_backtrace() 范例
<?php
// include.php file
function a() {
b();
}
function b() {
c();
}
function c(){
debug_print_backtrace();
}
a();
?>
<?php
// 文件 test.php
// 这是你应该运行的文件
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]
Sammaye (2011-02-24 04:26:18)
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 (2010-04-01 04:31:43)
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 (2009-07-28 13:20:13)
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 (2009-01-13 16:51:52)
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 (2008-11-10 21:51:21)
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 (2008-02-19 13:54:09)
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 (2007-08-21 04:52:03)
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 (2007-06-05 11:23:07)
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 (2007-03-28 02:10:37)
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 (2005-03-15 01:47:24)
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