2009-09-14 11 views
201

Sto cercando un modo per stampare lo stack di chiamate in PHP.Stampa PHP Call Stack

Punti bonus se la funzione svuota il buffer IO.

+2

possibile duplicato di [Come posso ottenere PHP per produrre un backtrace sugli errori?] (http://stackoverflow.com/questions/1159216/how-can-i-get-php-to-produce-a-backtrace-upon-errors) – Gordon

+10

... ma queste risposte sono meglio. – Ben

risposta

109

Se si desidera generare un backtrace, siete alla ricerca di debug_backtrace e/o debug_print_backtrace.


La prima volontà, per esempio, si ottiene una matrice come questo (citando il manuale):

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


Saranno a quanto pare non svuotare il buffer di I/O, ma puoi farlo da solo, con flush e/o ob_flush.

(si veda la pagina di manuale del primo per scoprire il motivo per cui la "e/o" ;-))

+5

questo regolarmente fa funzionare il mio php di memoria. Raccomando la soluzione di Tobiasz. – peedee

1

debug_backtrace()

3

Utilizzare debug_backtrace per ottenere un backtrace di quali funzioni e metodi sono stati chiamati e quali file sono stati inclusi che hanno portato al punto in cui è stato chiamato debug_backtrace.

6
var_dump(debug_backtrace()); 

Fa quello che vuoi?

416

più leggibile rispetto 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. Grazie. – shaune

+28

Accidenti, questo è molto meglio, perché non potrebbero rendere questo l'output di default per debug_print_backtrace()? Avrebbe potuto aggiungere un parametro booleano "returnTrace" per coloro che lo vogliono in una variabile, non echeggiato, e sarebbe stato perfetto! – jurchiks

+0

Non so quanti mesi ho cercato di capire come fare che non ho mai pensato che avrebbe funzionato – WojonsTech

32

per registrare il tracciato

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

Grazie @Tobiasz

27

Backtrace discariche un sacco di spazzatura che non è necessario. Ci vuole molto tempo, difficile da leggere. Tutto quello che tu vuoi sempre è "cosa si chiama cosa da dove?" Ecco una semplice soluzione di funzione statica. Di solito lo metto in una classe chiamata 'debug', che contiene tutte le mie funzioni di utilità di 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++; 
     } 
    } 
} 

si chiamano in questo modo:

debugUtils::callStack(debug_backtrace()); 

e produce un output simile a questo:

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

Quindi rendi $ element, o rinomina $ element a $ node, big deal ... – Hejazzman

+1

['file' e 'linea' non sono sempre presenti nel nodo $] (http://stackoverflow.com/a/6643478/ 210336) –

7

Se si desidera una traccia dello stack che sembra molto simile a come php formatta l'eccezione stack trace di utilizzare questa funzione che ho scritto:

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

Ciò restituirà una traccia dello stack formattato in questo modo:

#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 è un ottimo strumento per la stampa stack PHP in qualsiasi momento quando si desidera senza installare alcuna estensione.

Ci sono due principali funzioni di phptrace: in primo luogo, lo stack di chiamate di PHP che non richiede l'installazione di alcunché, in secondo luogo, i flussi di esecuzione di traccia php che devono installare l'estensione fornita.

come segue:

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

Esiste una versione per Windows? – johnny

18

Strano che nessuno ha postato in questo modo:

debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); 

Questo effettivamente stampa il backtrace senza la spazzatura - solo quale metodo è stato chiamato e dove.

+1

In effetti, davvero equivalente alla soluzione votata principale, e più breve. Grazie – brunetton

0

soluzione Walltearer è eccellente, soprattutto se racchiuso in un tag 'pre':

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

- che stabilisce le chiamate su linee separate, ordinatamente numerati