2009-09-14 38 views
201

Estoy buscando una manera de imprimir la pila de llamadas en PHP.Imprimir PHP Call Stack

Puntos de bonificación si la función vacía el búfer IO.

+2

posible duplicado de [¿Cómo puedo obtener PHP para producir una traza inversa sobre los errores?] (http://stackoverflow.com/questions/1159216/how-can-i-get-php-to-produce-a-backtrace-upon-errors) – Gordon

+10

... pero estas respuestas son mejores. – Ben

Respuesta

109

Si desea generar la traza, que busca debug_backtrace y/o debug_print_backtrace.


La primera de ellas, por ejemplo, se obtiene un conjunto como éste (citando el manual):

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


Al parecer, no vaciar el búfer de E/S, pero puede hacerlo usted mismo, con flush y/o ob_flush.

(ver la página del manual del primero para averiguar por qué el "y/o" ;-))

+5

esto regularmente hace que mi php se quede sin memoria. Recomiendo la solución de Tobiasz. – peedee

3

Utilice debug_backtrace para obtener un rastreo de qué funciones y métodos se han llamado y qué archivos se han incluido que llevaron al punto donde se ha llamado al debug_backtrace.

6
var_dump(debug_backtrace()); 

¿Hace eso que usted quiere?

416

más legible que 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. Gracias. – shaune

+28

Maldita sea, esto es mucho mejor, ¿por qué no podrían hacer de esto la salida predeterminada para debug_print_backtrace()? Podría haber agregado un parámetro booleano "returnTrace" para aquellos que lo quieran en una variable, sin eco, ¡y hubiera sido perfecto! – jurchiks

+0

No sé cuántos meses he intentado averiguar cómo hacerlo, nunca pensé que funcionaría – WojonsTech

32

para registrar la huella

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

Gracias @Tobiasz

27

Backtrace volcados una gran cantidad de basura que no es necesario. Se necesita mucho tiempo, es difícil de leer. Todo lo que siempre querrás es "¿qué llamó qué de dónde?" Aquí hay una solución de función estática simple. Normalmente lo pongo en una clase llamada 'depuración', que contiene todas mis funciones de utilidad de depuración.

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++; 
     } 
    } 
} 

Se llaman así:

debugUtils::callStack(debug_backtrace()); 

y produce una salida como ésta:

================================================== 
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

Por lo tanto, conviértalo en $ elemento, o renombre $ elemento en $ nodo, gran oferta ... – Hejazzman

+1

['archivo' y 'línea' no siempre están presentes en $ nodo] (http://stackoverflow.com/a/6643478/ 210336) –

7

Si quieres un seguimiento de la pila, que es muy similar a la forma en php formatea la excepción seguimiento de la pila que utilizar esta función escribí:

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

Esto devolverá un seguimiento de pila formateado como esto:

#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 es una gran herramienta para imprimir PHP pila en cualquier momento cuando desee sin necesidad de instalar ninguna extensión.

Hay dos funciones principales de phptrace: primero, imprimir la pila de llamadas de PHP que no necesita instalar nada, segundo, rastrear los flujos de ejecución de php que necesita para instalar la extensión que suministra.

de la siguiente manera:

$ ./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

¿Hay una versión de Windows? – johnny

18

extraño que nadie publicado de esta manera:

debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); 

Esto realmente imprime la traza inversa sin la basura, simplemente qué método se llamó y dónde.

+1

De hecho, es realmente equivalente a la solución principal votada, y más corta. Gracias – brunetton

0

solución de Walltearer es excelente, sobre todo si está cubierto por una etiqueta 'pre':

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

- que establece las llamadas en líneas separadas, numeradas ordenadamente