2009-09-14 113 views
201

我正在寻找一种在PHP中打印调用堆栈的方法。打印PHP调用堆栈

如果函数刷新IO缓冲区,则为奖励点。

+2

可能重复[我怎样才能PHP以产生错误回溯?](http://stackoverflow.com/questions/1159216/how-can-i-get-php-to-produce-a-backtrace-upon-errors) – Gordon

+10

...但这些回应更好。 – Ben

回答

109

如果你想生成一个回溯,你正在寻找debug_backtrace和/或debug_print_backtrace


第一个将,例如,让你像这样的(报价手册)数组

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" 
    } 
} 


他们显然不刷新I/O缓冲区,但你可以自己做,flush和/或ob_flush

(见第一个手册页,找出为什么“和/或” ;-))

+5

这经常让我的php耗尽内存。我推荐Tobiasz的解决方案。 – peedee

3

使用debug_backtrace可以回溯已调用的函数和方法,以及包含哪些文件导致调用debug_backtrace的点。

6
var_dump(debug_backtrace()); 

这是做你想做的?

416

更具可读性比debug_backtrace()

$e = new \Exception; 
var_dump($e->getTraceAsString()); 

#2 /usr/share/php/PHPUnit/Framework/TestCase.php(626): SeriesHelperTest->setUp() 
#3 /usr/share/php/PHPUnit/Framework/TestResult.php(666): PHPUnit_Framework_TestCase->runBare() 
#4 /usr/share/php/PHPUnit/Framework/TestCase.php(576): PHPUnit_Framework_TestResult->run(Object(SeriesHelperTest)) 
#5 /usr/share/php/PHPUnit/Framework/TestSuite.php(757): PHPUnit_Framework_TestCase->run(Object(PHPUnit_Framework_TestResult)) 
#6 /usr/share/php/PHPUnit/Framework/TestSuite.php(733): PHPUnit_Framework_TestSuite->runTest(Object(SeriesHelperTest), Object(PHPUnit_Framework_TestResult)) 
#7 /usr/share/php/PHPUnit/TextUI/TestRunner.php(305): PHPUnit_Framework_TestSuite->run(Object(PHPUnit_Framework_TestResult), false, Array, Array, false) 
#8 /usr/share/php/PHPUnit/TextUI/Command.php(188): PHPUnit_TextUI_TestRunner->doRun(Object(PHPUnit_Framework_TestSuite), Array) 
#9 /usr/share/php/PHPUnit/TextUI/Command.php(129): PHPUnit_TextUI_Command->run(Array, true) 
#10 /usr/bin/phpunit(53): PHPUnit_TextUI_Command::main() 
#11 {main}" 
+4

Ahhhhh。谢谢。 – shaune

+28

该死的,这太好了,他们为什么不能把它作为debug_print_backtrace()的默认输出?可以为那些想要变量的用户添加一个布尔参数“returnTrace”,而不是回显,它会是完美的! – jurchiks

+0

我不知道有多少个月来我一直在想如何做,从来没有想过它会工作 – WojonsTech

32

要记录跟踪

$e = new Exception; 
error_log(var_export($e->getTraceAsString(), true)); 

感谢@Tobiasz

27

回溯转储了一大堆的垃圾,你不需要的。它需要很长时间,难以阅读。你所有想要的只是“什么叫什么来自哪里?”这是一个简单的静态功能解决方案。我通常把它放在一个名为'debug'的类中,该类包含我所有的调试实用程序函数。

class debugUtils { 
    public static function callStack($stacktrace) { 
     print str_repeat("=", 50) ."\n"; 
     $i = 1; 
     foreach($stacktrace as $node) { 
      print "$i. ".basename($node['file']) .":" .$node['function'] ."(" .$node['line'].")\n"; 
      $i++; 
     } 
    } 
} 

你这样称呼它:

debugUtils::callStack(debug_backtrace()); 

而且它产生的输出是这样的:

================================================== 
1. DatabaseDriver.php::getSequenceTable(169) 
2. ClassMetadataFactory.php::loadMetadataForClass(284) 
3. ClassMetadataFactory.php::loadMetadata(177) 
4. ClassMetadataFactory.php::getMetadataFor(124) 
5. Import.php::getAllMetadata(188) 
6. Command.php::execute(187) 
7. Application.php::run(194) 
8. Application.php::doRun(118) 
9. doctrine.php::run(99) 
10. doctrine::include(4) 
================================================== 
+4

因此,使它$元,或$元重命名为$节点,大不了... – Hejazzman

+1

['文件'和'线'并不总是在$节点](http://stackoverflow.com/a/6643478/ 210336) –

7

如果你想有一个堆栈跟踪看起来非常相似,PHP如何格式化例外堆栈跟踪比使用这个功能我写道:

function debug_backtrace_string() { 
    $stack = ''; 
    $i = 1; 
    $trace = debug_backtrace(); 
    unset($trace[0]); //Remove call to this function from stack trace 
    foreach($trace as $node) { 
     $stack .= "#$i ".$node['file'] ."(" .$node['line']."): "; 
     if(isset($node['class'])) { 
      $stack .= $node['class'] . "->"; 
     } 
     $stack .= $node['function'] . "()" . PHP_EOL; 
     $i++; 
    } 
    return $stack; 
} 

这将返回格式化这样的堆栈跟踪:

#1 C:\Inetpub\sitename.com\modules\sponsors\class.php(306): filePathCombine() 
#2 C:\Inetpub\sitename.com\modules\sponsors\class.php(294): Process->_deleteImageFile() 
#3 C:\Inetpub\sitename.com\VPanel\modules\sponsors\class.php(70): Process->_deleteImage() 
#4 C:\Inetpub\sitename.com\modules\sponsors\process.php(24): Process->_delete() 
3

phptrace是打印PHP堆栈随时一个伟大的工具,当你想无需安装任何扩展。

phptrace有两大功能:一是打印不需要安装任何东西的PHP调用堆栈,二是跟踪php需要安装它所提供的扩展的执行流程。

如下:

$ ./phptrace -p 3130 -s    # phptrace -p <PID> -s 
phptrace 0.2.0 release candidate, published by infra webcore team 
process id = 3130 
script_filename = /home/xxx/opt/nginx/webapp/block.php 
[0x7f27b9a99dc8] sleep /home/xxx/opt/nginx/webapp/block.php:6 
[0x7f27b9a99d08] say /home/xxx/opt/nginx/webapp/block.php:3 
[0x7f27b9a99c50] run /home/xxx/opt/nginx/webapp/block.php:10 
+0

是否有Windows版本? – johnny

18

奇怪的是,没有人发布这种方式:

debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); 

这实际上打印没有垃圾回溯 - 只是调用什么方法和在哪里。

+1

的确,真的相当于主投票的解决方案,而且更短。 谢谢 – brunetton

0

Walltearer的解决方案是出色的,特别是如果封闭在一个“前”标签:

<pre> 
<?php debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); ?> 
</pre> 

- 其中规定了单独行上调用,整齐编号的