debug_backtrace
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
debug_backtrace — バックトレースを生成する
説明
debug_backtrace() は PHP バックトレースを生成します。
パラメータ
options
-
このパラメータは次のオプションのビットマスクとなります。
debug_backtrace() のオプション DEBUG_BACKTRACE_PROVIDE_OBJECT "object" インデックスを埋めるかどうか。 DEBUG_BACKTRACE_IGNORE_ARGS "args" インデックス、 すなわちすべての関数/メソッドの引数を省略してメモリを節約するかどうか。 注意:
可能な組み合わせは以下の4つです:
debug_backtrace() のオプション debug_backtrace()
インデックスを両方収集します。 debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT)
debug_backtrace(1)
debug_backtrace(0)
インデックス "object"
を省略し、"args"
を収集します。debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)
インデックス "object"
と"args"
を 両方省略します。debug_backtrace(2)
debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT|DEBUG_BACKTRACE_IGNORE_ARGS)
インデックス "object"
を収集し、"args"
を省略します。debug_backtrace(3)
limit
-
このパラメータを使ってスタックフレームの数を制限できます。 デフォルト (
limit
=0
) は、すべてのスタックフレームを返します。
戻り値
連想配列の配列を返します。連想配列の要素として返される可能性があるものは以下のとおりです。
名前 | 型 | 説明 |
---|---|---|
function | string | カレントの関数名。 __FUNCTION__ も参照ください。 |
line | int | カレントの行番号。 __LINE__ も参照ください。 |
file | string | カレントのファイル名。 __FILE__ も参照ください。 |
class | string | カレントのクラス名。 __CLASS__ も参照ください。 |
object | object | カレントのオブジェクト。 |
type | string | カレントのコール方式。メソッドを呼び出している場合は "->"、 staticメソッドを呼び出している場合は "::" が返されます。 関数呼び出しの場合は何も返されません。 |
args | array | 関数の内部の場合、関数の引数のリストとなります。 インクルードされたファイル内では、 読み込まれたファイルの名前となります。 |
例
例1 debug_backtrace() の例
<?php
// ファイル名: /tmp/a.php
function a_test($str)
{
echo "\nHi: $str";
var_dump(debug_backtrace());
}
a_test('friend');
?>
<?php
// ファイル名: /tmp/b.php
include_once '/tmp/a.php';
?>
/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" } }
+add a note
User Contributed Notes 37 notes
jurchiks101 at gmail dot com ¶
11 years ago
Here's a function I just wrote for getting a nice and comprehensible call trace. It is probably more resource-intensive than some other alternatives but it is short, understandable, and gives nice output (Exception->getTraceAsString()).
<?php
function generateCallTrace()
{
$e = new Exception();
$trace = explode("\n", $e->getTraceAsString());
// reverse array to make steps line up chronologically
$trace = array_reverse($trace);
array_shift($trace); // remove {main}
array_pop($trace); // remove call to this method
$length = count($trace);
$result = array();
for ($i = 0; $i < $length; $i++)
{
$result[] = ($i + 1) . ')' . substr($trace[$i], strpos($trace[$i], ' ')); // replace '#someNum' with '$i)', set the right ordering
}
return "\t" . implode("\n\t", $result);
}
?>
Example output:
1) /var/www/test/test.php(15): SomeClass->__construct()
2) /var/www/test/SomeClass.class.php(36): SomeClass->callSomething()
liam at N0SPAM dot boxclever dot ca ¶
1 year ago
Options provided by bitmask parameters can be disabled using !
<?php
debug_backtrace( !DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
?>
robert at medianis dot net ¶
8 years ago
Just a short note on debug_backtrace options for PHP 5.3.6 or newer:
debug_backtrace() - show all options
debug_backtrace(0) - exlude ["object"]
debug_backtrace(1) - same as debug_backtrace()
debug_backtrace(2) - exlude ["object"] AND ["args"]
use this example and try calling debug_backtrace with different options
<?php
function F1()
{
echo "<br />";
echo "in F1 now";
echo "<pre>".print_r(debug_backtrace(2),true)."</pre>";
}
class DebugOptionsTest
{
function F2()
{
echo "<br />";
echo "in F2 now";
F1();
}
}
echo "<hr />calling F1";
F1();
$c=new DebugOptionsTest();
echo "<hr /><hr /><hr />calling F2";
$c->F2("testValue");
?>
jsnell at e-normous dot com ¶
17 years ago
If you are using the backtrace function in an error handler, avoid using var_export() on the args, as you will cause fatal errors in some situations, preventing you from seeing your stack trace. Some structures will cause PHP to generate the fatal error "Nesting level too deep - recursive dependency?" This is a design feature of php, not a bug (see http://bugs.php.net/bug.php?id=30471)
michael dot schramm at gmail dot com ¶
14 years ago
Be carefull if you are using objects as arguments for function calls!
<?php
error_reporting(E_ALL);
function myPrint($trace){
foreach($trace as $i=>$call){
/**
* THIS IS NEEDED! If all your objects have a __toString function it's not needed!
*
* Catchable fatal error: Object of class B could not be converted to string
* Catchable fatal error: Object of class A could not be converted to string
* Catchable fatal error: Object of class B could not be converted to string
*/
if (is_object($call['object'])) { $call['object'] = 'CONVERTED OBJECT OF CLASS '.get_class($call['object']); }
if (is_array($call['args'])) {
foreach ($call['args'] AS &$arg) {
if (is_object($arg)) { $arg = 'CONVERTED OBJECT OF CLASS '.get_class($arg); }
}
}
$trace_text[$i] = "#".$i." ".$call['file'].'('.$call['line'].') ';
$trace_text[$i].= (!empty($call['object'])?$call['object'].$call['type']:'');
$trace_text[$i].= $call['function'].'('.implode(', ',$call['args']).')';
}
var_dump($trace_text);
}
class A{
public function test($obj){
$obj->test();
}
}
class B{
public function test(){
echo myPrint(debug_backtrace());
}
}
$A = new A();
$B = new B();
$A->test($B);
?>
http://synergy8.com ¶
18 years ago
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
}
?>
Emmett Brosnan ¶
8 years ago
Quick and dirty formatted output from debug_backtrace.
$file_paths = debug_backtrace();
foreach($file_paths AS $file_path) {
foreach($file_path AS $key => $var) {
if($key == 'args') {
foreach($var AS $key_arg => $var_arg) {
echo $key_arg . ': ' . $var_arg . '<br>';
}
} else {
echo $key . ': ' . $var . '<br>';
}
}
}
jcmargentina at gmail dot com ¶
5 years ago
I want to point out that debug_backtrace() in new versions of php can detect recursion // circular references .. avoiding memory consumption.
Example:
<?php
class ParentClass {
public function __construct()
{
$this->_child = new ChildClass($this);
var_dump(debug_backtrace());
}
}
class ChildClass {
public function __construct(ParentClass $p)
{
$this->_parent = $p;
}
}
$test = new ParentClass();
?>
Output:
array(1) {
[0]=>
array(7) {
["file"]=>
string(23) "/home/jcm/testdebug.php"
["line"]=>
int(18)
["function"]=>
string(11) "__construct"
["class"]=>
string(11) "ParentClass"
["object"]=>
object(ParentClass)#1 (1) {
["_child"]=>
object(ChildClass)#2 (1) {
["_parent"]=>
*RECURSION*
}
}
["type"]=>
string(2) "->"
["args"]=>
array(0) {
}
}
}
Attention in the *RECURSION* hint provided
root at jackyyf dot com ¶
11 years ago
When use register_shutdown_function, and the function called when shutting down, there are no line number nor filename information about this function, only function, class(if possible), type(if possible) and args are provided.
Bill Getas ¶
13 years ago
Here's my little updated contribution - it prints colorful output in the way I prefer. Define a helper function isRootIp() that contains an array including your IP; then calls to bt() simply return, so you can sprinkle backtraces in live sites w/o anyone knowing.
<?php
function bt()
{
if( ! isRootIp() )
{
return false;
}
array_walk( debug_backtrace(), create_function( '$a,$b', 'print "<br /><b>". basename( $a[\'file\'] ). "</b> <font color=\"red\">{$a[\'line\']}</font> <font color=\"green\">{$a[\'function\']} ()</font> -- ". dirname( $a[\'file\'] ). "/";' ) );
}
?>
Anonymous ¶
11 years ago
Simple function to get a string in form "filename: [class->][function(): ]"
<?php
function get_caller_info() {
$c = '';
$file = '';
$func = '';
$class = '';
$trace = debug_backtrace();
if (isset($trace[2])) {
$file = $trace[1]['file'];
$func = $trace[2]['function'];
if ((substr($func, 0, 7) == 'include') || (substr($func, 0, 7) == 'require')) {
$func = '';
}
} else if (isset($trace[1])) {
$file = $trace[1]['file'];
$func = '';
}
if (isset($trace[3]['class'])) {
$class = $trace[3]['class'];
$func = $trace[3]['function'];
$file = $trace[2]['file'];
} else if (isset($trace[2]['class'])) {
$class = $trace[2]['class'];
$func = $trace[2]['function'];
$file = $trace[1]['file'];
}
if ($file != '') $file = basename($file);
$c = $file . ": ";
$c .= ($class != '') ? ":" . $class . "->" : "";
$c .= ($func != '') ? $func . "(): " : "";
return($c);
}
?>
Usage like:
<?php
function debug($str) {
echo get_caller_info() . $str . "<br>\n";
}
?>
get_caller_info() will return info about the function /class->method that called debug().
jonas at faceways dot se ¶
11 years ago
When using debug_backtrace() to check if you're being accessed from another caller, please remember to ask debug_backtrace to only go as far as needed in depth and skip taking the entire debug object as return parameter:
<?php
if (count(debug_backtrace(FALSE, 1)) == 0)
{
// Do something
}
?>
anoam at yandex dot ru ¶
10 years ago
It works a little bit different with resources in different PHP versions.
For example:
function foo($bar)
{
return debug_backtrace();
}
$resource = fopen(__FILE__, 'r');
$backtrace = foo($resource);
echo "when resource is opened: " . gettype($backtrace[0]['args'][0]) . "\n";
fclose($resource);
echo "when resource is closed: " . gettype($backtrace[0]['args'][0]) . "\n";
With 5.3.10 I got:
when resource is opened: resource
when resource is closed: resource
With 5.5.9:
when resource is opened: resource
when resource is closed: unknown type
Be carefull.
jlammertink at gmail dot com ¶
14 years ago
I use this simple but effective function so i can see which method in the child class called the current method (in the parent class).
<?php
function get_caller_method()
{
$traces = debug_backtrace();
if (isset($traces[2]))
{
return $traces[2]['function'];
}
return null;
}
?>
d at rren dot me ¶
12 years ago
Howdy guys, just a note really - The ['args'] data within the resulting array is supplied by reference. I found myself editing the reference unknowingly which in turn shows its ugly head further down the line if you call multiple backtrace.
<?php
$trace = array_reverse(debug_backtrace());
// LOOP BACKTRACE
$la = 0;
$lb = count($trace);
while ($la<$lb){
// DATA FROM BACKTRACE
$trace[$la]['file'];
$trace[$la]['line'];
$trace[$la]['args'];
$trace[$la]['function'];
// DATA FROM BACKTRACE
// LOOP ARGUMENTS ARRAY
$ba = 0;
$bb = count($trace[$la]['args']);
while ($ba<$bb){
$trace[$la]['args'][$ba] = "EDITING A REFERENCE/POINTER";
$ba++;
}
unset($bb);
unset($ba);
// LOOP ARGUMENTS ARRAY
$la++;
}
unset($lb);
unset($la);
// LOOP BACKTRACE
?>
kroczu AT interia DOT pl ¶
17 years ago
<?
// useful and comfortable debug function
// it's show memory usage and time flow between calls, so we can quickly find a block of code that need optimisation...
// example result:
/*
debug example.php> initialize
debug example.php> code-lines: 39-41 time: 2.0002 mem: 19 KB
debug example.php> code-lines: 41-44 time: 0.0000 mem: 19 KB
debug example.php> code-lines: 44-51 time: 0.6343 mem: 9117 KB
debug example.php> code-lines: 51-53 time: 0.1003 mem: 9117 KB
debug example.php> code-lines: 53-55 time: 0.0595 mem: 49 KB
*/
function debug()
{
static $start_time = NULL;
static $start_code_line = 0;
$call_info = array_shift( debug_backtrace() );
$code_line = $call_info['line'];
$file = array_pop( explode('/', $call_info['file']));
if( $start_time === NULL )
{
print "debug ".$file."> initialize\n";
$start_time = time() + microtime();
$start_code_line = $code_line;
return 0;
}
printf("debug %s> code-lines: %d-%d time: %.4f mem: %d KB\n", $file, $start_code_line, $code_line, (time() + microtime() - $start_time), ceil( memory_get_usage()/1024));
$start_time = time() + microtime();
$start_code_line = $code_line;
}
////////////////////////////////////////////////
// example:
debug();
sleep(2);
debug();
// soft-code...
$a = 3 + 5;
debug();
// hard-code
for( $i=0; $i<100000; $i++)
{
$dummy['alamakota'.$i] = 'alamakota'.$i;
}
debug();
usleep(100000);
debug();
unset($dummy);
debug();
?>
seaside dot ki at mac dot com ¶
17 years ago
I've started creating an external debug server for PHP. A PHP app require_once's a TADebugger(), which communicates with the debug sever. Find the OS X universal binary here [PHP source sample included]:
http://www.turingart.com/downloads/phpDebugger.zip
Currently, TADebugger allows to post these properties back to the debug server:
- Call backtraces
- String messages
- Source files, which were referenced by a backtrace call
Note, that the binary is a early version.
admin at sgssweb dot com ¶
18 years ago
Surprizingly, debug_backtrace() cannot aquire arguments from the function that is used as the second or later argument of a function.
<?php
function a($p) {
$backtrace = debug_backtrace();
if (isset($backtrace[0]['args']))
var_export($backtrace[0]['args']);
else
echo "Cannot aquire arguments";
echo "<br />";
return $p;
}
function b($p1, $p2, $p3) {
echo "$p1, $p2, $p3";
}
// This outputs:
// array ( 0 => 'First a', )
// Cannot aquire arguments
// Cannot aquire arguments
// First a, Second a, Third a
b(a("First a"), a("Second a"), a("Third a"));
?>
kenorb at gmail dot com ¶
14 years ago
One line of code to print simplest and shortest human readable backtrace:)
<?php
array_walk(debug_backtrace(),create_function('$a,$b','print "{$a[\'function\']}()(".basename($a[\'file\']).":{$a[\'line\']}); ";'));
?>
jake at qzdesign dot co dot uk ¶
5 years ago
The `args` element contains only the arguments actually passed to the function or method. It does not include default parameters if they were not explicitly specified. (A least, this is the case with PHP 7.1.9.) This is consistent with the behaviour of `func_get_args()`.