Je cherche un moyen d'imprimer la pile d'appels en PHP.
Points bonus si la fonction vide le tampon IO.
Si vous souhaitez générer une trace, vous recherchez debug_backtrace
et/ou debug_print_backtrace
.
Le premier, par exemple, vous donnera un tableau comme celui-ci (citant le manuel):
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"
}
}
Apparemment, ils ne videront pas le tampon d’E/S, mais vous pouvez le faire vous-même, avec flush
et/ou ob_flush
.
(voir la page de manuel du premier pour savoir pourquoi "et/ou" ;-))}
Plus lisible 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}"
Pour enregistrer la trace
$e = new Exception;
error_log(var_export($e->getTraceAsString(), true));
Merci @Tobiasz
Backtrace jette beaucoup de déchets inutiles. C'est très long, difficile à lire. Tout ce que vous voulez habituellement, c’est «comment on appelle quoi d’où? Voici une solution de fonction statique simple. Je le mets généralement dans une classe appelée 'debug', qui contient toutes mes fonctions utilitaires de débogage.
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++;
}
}
}
Vous l'appelez comme ça:
debugUtils::callStack(debug_backtrace());
Et cela produit une sortie comme ceci:
==================================================
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)
==================================================
Étrange que personne n'a posté de cette façon:
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
En fait, cela affiche la trace sans les ordures - quelle méthode a été appelée et où.
Si vous voulez une trace de pile qui ressemble beaucoup à la façon dont php formate la trace de pile d'exception, utilisez cette fonction, j'ai écrit:
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;
}
Cela retournera une trace de pile formatée comme ceci:
#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());
Est-ce que ça fait ce que tu veux?
Voir debug_print_backtrace
. Je suppose que vous pouvez appeler flush
après si vous le souhaitez.
phptrace est un excellent outil pour imprimer la pile PHP à tout moment, sans aucune extension.
Il existe deux fonctions principales de phptrace: premièrement, imprimer la pile d'appels de PHP qui ne nécessite aucune installation, deuxièmement, tracer les flux d'exécution php nécessitant l'installation de l'extension fournie.
comme suit:
$ ./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
Utilisez debug_backtrace
pour obtenir une trace des fonctions et méthodes appelées et des fichiers inclus qui ont conduit au point où debug_backtrace
a été appelé.
s'il vous plaît jeter un oeil à cette classe utils, peut être utile:
Usage:
<?php
/* first caller */
Who::callme();
/* list the entire list of calls */
Who::followme();
Classe source: https://github.com/augustowebd/utils/blob/master/Who.php
debug_backtrace()
Vous voudrez peut-être regarder dans debug_backtrace
, ou peut-être debug_print_backtrace
.
La solution de Walltearer est excellente, particulièrement si elle est incluse dans une balise 'pre':
<pre>
<?php debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); ?>
</pre>
- qui établit les appels sur des lignes séparées, soigneusement numérotées
J'ai adapté la réponse de Don Briggs ci-dessus pour utiliser la consignation des erreurs internes au lieu de l'impression publique, ce qui peut être votre principale préoccupation lorsque vous travaillez sur un serveur en direct. De plus, quelques modifications supplémentaires ont été ajoutées, telles que l'option permettant d'inclure le chemin d'accès complet au lieu du nom de base (car il pourrait y avoir des fichiers portant le même nom dans des chemins d'accès différents), ainsi qu'une sortie complète de la pile de nœuds (pour ceux qui en ont besoin):
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());