PHP Call Stack drucken

Antworten:

123

Wenn Sie eine Rückverfolgung generieren möchten, suchen Sie debug_backtraceund / oder debug_print_backtrace.


Mit dem ersten erhalten Sie beispielsweise ein Array wie dieses (unter Angabe des Handbuchs) :

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


Sie werden den E / A-Puffer anscheinend nicht leeren, aber Sie können dies selbst tun, mit flushund / oder ob_flush.

(Siehe die Handbuchseite der ersten, um herauszufinden, warum das "und / oder" ;-))

Pascal MARTIN
quelle
7
Dadurch geht meinem PHP regelmäßig der Speicher aus. Ich empfehle die Lösung von Tobiasz.
Peedee
Wenn Sie
Schwierigkeiten
1
@peedee Sie müssen lediglich einen der optionalen DEBUG_BACKTRACE_IGNORE_ARGSParameter angeben . das macht sie funktional äquivalent zu(new \Exception())->getTraceAsString()
565

Lesbarer als 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}"
Tobias Cudnik
quelle
50
Verdammt, das ist so viel besser, warum konnten sie dies nicht zur Standardausgabe für debug_print_backtrace () machen? Könnte einen booleschen Parameter "returnTrace" für diejenigen hinzugefügt haben, die es in einer Variablen wollen, die nicht wiedergegeben wird, und es wäre perfekt gewesen!
Jurchiks
1
Ich weiß nicht, wie viele Monate ich versucht habe herauszufinden, wie das geht, hätte nie gedacht, dass es funktionieren würde
WojonsTech
Diese Lösung scheint auch weniger Speicherplatz zu beanspruchen, als die Ausgabe von debug_backtrace () als Array zu erfassen und dann mit print_r () zu drucken, was ich getan habe, bis ich das gesehen habe!
Peter
5
Ich suchte nach einer Möglichkeit zur Begrenzung, debug_backtraceum nur die erste Ebene im Stacktrace zurückzugeben - diese Lösung erledigt die Arbeit für mich. Danke dir!
ankr
3
@ Andrew print_rbehält alle Nachrichten.
Mopo922
41

So protokollieren Sie den Trace

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

Danke @Tobiasz

Sydwell
quelle
35

Backtrace wirft eine Menge Müll weg, den Sie nicht brauchen. Es dauert sehr lange, schwer zu lesen. Alles, was Sie normalerweise jemals wollen, ist: "Wie heißt was von wo?" Hier ist eine einfache statische Funktionslösung. Normalerweise stelle ich es in eine Klasse namens 'debug', die alle meine Debugging-Dienstprogrammfunktionen enthält.

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

Sie nennen es so:

debugUtils::callStack(debug_backtrace());

Und es erzeugt eine Ausgabe wie folgt:

==================================================
 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)
==================================================
Don Briggs
quelle
33

Seltsam, dass niemand so gepostet hat:

debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);

Dies druckt tatsächlich die Rückverfolgung ohne den Müll - genau welche Methode wurde wo aufgerufen.

AbstractVoid
quelle
2
In der Tat wirklich gleichbedeutend mit der Hauptlösung und kürzer. Danke
Brunetton
9

Wenn Sie einen Stack-Trace möchten, der dem Formatieren des Exception-Stack-Trace durch PHP sehr ähnlich sieht, verwenden Sie diese von mir geschriebene Funktion:

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

Dies gibt einen Stack-Trace zurück, der wie folgt formatiert ist:

#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() 
TroySteven
quelle
2
oder einfach$e = new Exception; echo $e->getTraceAsString();
Brad Kent
Brad, diese Lösung entfernt nicht das letzte Element aus dem Stack-Trace, sodass Sie das durch die neue Ausnahme verursachte Trace-Element nicht
anzeigen
8
var_dump(debug_backtrace());

Macht das was du willst?

inkedmn
quelle
6

Siehe debug_print_backtrace. Ich denke, Sie können flushdanach anrufen, wenn Sie wollen.

Martin Geisler
quelle
4

phptrace ist ein großartiges Tool, um PHP-Stacks jederzeit zu drucken, ohne Erweiterungen zu installieren.

Es gibt zwei Hauptfunktionen von phptrace: erstens den Druckaufrufstapel von PHP, der nichts installieren muss, zweitens den Ablauf der PHP-Ausführungsabläufe, die die von ihm bereitgestellte Erweiterung installieren müssen.

wie folgt:

$ ./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 
renenglisch
quelle
Gibt es eine Windows-Version?
Johnny
Ich mag die Speicheradresse hier angezeigt werden. Dies kann hilfreich sein
Tyler Miles
3

Verwenden Sie debug_backtracediese Option, um einen Rückblick darauf zu erhalten, welche Funktionen und Methoden aufgerufen wurden und welche Dateien enthalten waren, die zu dem Punkt führten, an dem debug_backtracesie aufgerufen wurden.

Gumbo
quelle
1

debug_backtrace()

pix0r
quelle
1

Die Lösung von Walltearer ist hervorragend, insbesondere wenn sie in einem Pre-Tag eingeschlossen ist:

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

- die die Anrufe auf getrennten Leitungen anzeigt, ordentlich nummeriert

Geoff Kendall
quelle
0

Ich habe die Antwort von Don Briggs oben angepasst , um die interne Fehlerprotokollierung anstelle des öffentlichen Drucks zu verwenden. Dies kann Ihr großes Problem sein, wenn Sie an einem Live-Server arbeiten. Außerdem wurden einige weitere Änderungen hinzugefügt, z. B. die Option, anstelle des Basisnamens den vollständigen Dateipfad einzuschließen (da sich möglicherweise Dateien mit demselben Namen in unterschiedlichen Pfaden befinden) und (für diejenigen, die dies benötigen) eine vollständige Ausgabe des Knotenstapels:

class debugUtils {
    public static function callStack($stacktrace) {
        error_log(str_repeat("=", 100));
        $i = 1;
        foreach($stacktrace as $node) {
            // uncomment next line to debug entire node stack
            // error_log(print_r($node, true));
            error_log( $i . '.' . ' file: ' .$node['file'] . ' | ' . 'function: ' . $node['function'] . '(' . ' line: ' . $node['line'] . ')' );
            $i++;
        }
        error_log(str_repeat("=", 100));
    } 
}

// call debug stack
debugUtils::callStack(debug_backtrace());
dev101
quelle