301 votes

Imprimer la pile d'appels PHP

Je cherche un moyen d'imprimer la pile d'appels en PHP.

Des points bonus si la fonction vide le tampon IO.

2 votes

18 votes

...mais ces réponses sont meilleures.

664voto

Tobiasz Cudnik Points 2542

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

63 votes

Bon sang, c'est tellement mieux, pourquoi ne pas en faire la sortie par défaut de debug_print_backtrace() ? On aurait pu ajouter un paramètre booléen "returnTrace" pour ceux qui veulent le mettre dans une variable, et non pas en écho, et ça aurait été parfait !

1 votes

Je ne sais pas depuis combien de mois j'essaie de trouver comment faire ça, je ne pensais pas que ça marcherait.

0 votes

Cette solution semble également nécessiter moins de mémoire que de capturer la sortie de debug_backtrace() dans un tableau et de l'imprimer avec print_r(), ce que je faisais jusqu'à ce que je voie ceci !

137voto

Pascal MARTIN Points 195780

Si vous voulez générer un backtrace, vous recherchez debug_backtrace et/ou debug_print_backtrace .

La première vous permettra, par exemple, d'obtenir 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 le "et/ou" ;-) )

7 votes

Cela fait régulièrement que mon php se retrouve à court de mémoire. Je recommande la solution de Tobiasz.

0 votes

Si vous trouvez que c'est difficile à lire/comprendre, je recommande également la solution de Tobiasz

2 votes

@peedee, il suffit de fournir l'une des options suivantes DEBUG_BACKTRACE_IGNORE_ARGS ce qui les rend fonctionnellement équivalents à (new \Exception())->getTraceAsString()

44voto

Sydwell Points 1625

Pour enregistrer la trace

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

Merci @Tobiasz

39voto

Don Briggs Points 370

Backtrace déverse un tas de déchets dont vous n'avez pas besoin. Il est très long, difficile à lire. Tout ce que vous voulez, c'est "qu'est-ce qui a appelé quoi, d'où ?". Voici une solution simple pour les fonctions statiques. Je la place 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++;
        }
    } 
}

Tu l'appelles comme ça :

debugUtils::callStack(debug_backtrace());

Et ça donne un résultat comme celui-ci :

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

0 votes

Pourquoi ne pas ajouter les paramètres à ces appels de fonction ? Le nom de la classe est également disponible pour les fonctions membres de la classe. Vous pouvez faire un peu plus de code, puis publier ceci sur GitHub.

6voto

Martin Geisler Points 44779

Voir debug_print_backtrace . Je suppose que vous pouvez appeler flush après si vous le souhaitez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X