Risposte:
Se si desidera generare una backtrace, si sta cercando debug_backtrace
e / o debug_print_backtrace
.
Il primo, ad esempio, ti offrirà un array 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"
}
}
Apparentemente non svuoteranno il buffer I / O, ma puoi farlo tu stesso, con flush
e / o ob_flush
.
(vedere la pagina del manuale del primo per scoprire perché "e / o" ;-))
Più leggibile di 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}"
debug_backtrace
solo il ritorno al primo livello nello stacktrace: questa soluzione fa il lavoro per me. Grazie!
print_r
conserverà tutti i messaggi.
Backtrace scarica un sacco di immondizia che non ti serve. Ci vuole molto tempo, difficile da leggere. Tutto ciò che di solito volete è "ciò che ha chiamato cosa da dove?" Ecco una semplice soluzione con funzioni statiche. Di solito lo inserisco 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++;
}
}
}
Lo chiami così:
debugUtils::callStack(debug_backtrace());
E produce output in questo modo:
==================================================
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)
==================================================
Strano che nessuno abbia pubblicato in questo modo:
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
Questo in realtà stampa backtrace senza immondizia - solo quale metodo è stato chiamato e dove.
Se vuoi una traccia dello stack che assomigli molto al modo in cui php formatta la traccia dello stack delle eccezioni rispetto all'uso di questa funzione, 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 formattata 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()
$e = new Exception; echo $e->getTraceAsString();
Vedere debug_print_backtrace
. Immagino che tu possa chiamare flush
dopo se vuoi.
phptrace è un ottimo strumento per stampare lo stack PHP ogni volta che vuoi senza installare alcuna estensione.
Esistono due funzioni principali di phptrace: in primo luogo, stampare lo stack di chiamate di PHP che non ha bisogno di installare nulla, in secondo luogo, tracciare i flussi di esecuzione di 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
Utilizzare debug_backtrace
per ottenere una traccia indietro di quali funzioni e metodi sono stati chiamati e quali file sono stati inclusi che hanno portato al punto in cui debug_backtrace
è stato chiamato.
dai un'occhiata a questa classe utils, può essere utile:
Uso:
<?php
/* first caller */
Who::callme();
/* list the entire list of calls */
Who::followme();
Classe di provenienza : https://github.com/augustowebd/utils/blob/master/Who.php
Potresti voler esaminare debug_backtrace
, o forse debug_print_backtrace
.
La soluzione di Walltearer è eccellente, in particolare se racchiusa in un tag 'pre':
<pre>
<?php debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); ?>
</pre>
- che stabilisce le chiamate su linee separate, ordinatamente numerate
Ho adattato la risposta di Don Briggs sopra per utilizzare la registrazione degli errori interna anziché la stampa pubblica, che potrebbe essere la tua principale preoccupazione quando si lavora su un server live. Inoltre, sono state aggiunte alcune ulteriori modifiche come l'opzione per includere il percorso completo del file anziché il nome di base (perché, potrebbero esserci file con lo stesso nome in percorsi diversi) e anche (per coloro che lo richiedono) un output completo dello stack dei nodi:
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());