Ich suche nach einer Möglichkeit, den Aufrufstack in PHP zu drucken.
Bonuspunkte, wenn die Funktion den IO -Puffer leert.
Wenn Sie eine Rückverfolgung erzeugen möchten, suchen Sie nach debug_backtrace
und/oder debug_print_backtrace
.
Der erste bekommt zum Beispiel ein Array wie dieses (zitiert das Handbuch):
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 mit flush
und/oder ob_flush
.
(siehe Handbuchseite der ersten Seite, um herauszufinden, warum das "und/oder" ;-))}
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}"
So protokollieren Sie die Ablaufverfolgung
$e = new Exception;
error_log(var_export($e->getTraceAsString(), true));
Danke @Tobiasz
Backtrace Dumps eine Menge Müll, die Sie nicht brauchen. Es dauert sehr lange und ist schwer zu lesen. Alles, was Sie normalerweise wollen, ist "Was nannte was von wo?" Hier ist eine einfache statische Funktionslösung. Normalerweise stelle ich es in eine Klasse namens 'debug', die alle meine Debugging-Funktionen 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 produziert 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)
==================================================
Seltsam, dass niemand so geschrieben hat:
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
Dies druckt tatsächlich eine Rückverfolgung ohne den Müll - genau welche Methode wurde wo aufgerufen.
Wenn Sie eine Stack-Ablaufverfolgung wünschen, die der Formatierung der Ausnahmestapel-Ablaufverfolgung sehr ähnelt, verwenden Sie die von mir beschriebene 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;
}
Dadurch wird eine Stapelablaufverfolgung zurückgegeben, die folgendermaßen 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()
var_dump(debug_backtrace());
Tun das, was du willst?
Siehe debug_print_backtrace
. Ich denke, Sie können später flush
aufrufen, wenn Sie möchten.
phptrace ist ein großartiges Werkzeug zum Drucken des PHP - Stapels, wann immer Sie möchten, ohne Erweiterungen zu installieren.
Es gibt zwei Hauptfunktionen von phptrace: erstens den Call-Stack von PHP, der nichts zu installieren braucht, zweitens, Ablaufverfolgungs-PHP-Ausführungsflüsse, 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
Verwenden Sie debug_backtrace
, um zu erfahren, welche Funktionen und Methoden aufgerufen wurden und welche Dateien enthalten waren, die zu dem Punkt führten, an dem debug_backtrace
aufgerufen wurde.
bitte schauen Sie sich diese utils-Klasse an, vielleicht hilfreich:
Verwendungszweck:
<?php
/* first caller */
Who::callme();
/* list the entire list of calls */
Who::followme();
Quellklasse: https://github.com/augustowebd/utils/blob/master/Who.php
debug_backtrace()
Vielleicht möchten Sie nach debug_backtrace
oder vielleicht debug_print_backtrace
suchen.
Die Lösung von Walltearer ist ausgezeichnet, besonders wenn sie in einem "pre" -Tag enthalten ist:
<pre>
<?php debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); ?>
</pre>
- die die Anrufe auf separaten Leitungen mit sauberer Nummerierung festlegt
Ich habe Don Briggs 'Antwort so angepasst, dass anstelle des öffentlichen Druckens die interne Fehlerprotokollierung verwendet wird, was bei der Arbeit an einem Live-Server möglicherweise ein großes Problem ist. Außerdem wurden einige weitere Modifikationen hinzugefügt, z. B. die Option, den vollständigen Dateipfad anstelle des Basisnamens einzuschließen (da möglicherweise Dateien mit demselben Namen in unterschiedlichen Pfaden vorhanden sind) und (für diejenigen, die dies erfordern) 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());