web-dev-qa-db-fra.com

Impression PHP Pile d'appels

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

Points bonus si la fonction vide le tampon IO.

223
Justin

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

114
Pascal MARTIN

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}"
489
Tobiasz Cudnik

Pour enregistrer la trace

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

Merci @Tobiasz

37
Sydwell

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

É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ù.

29
WallTearer

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() 
10
matwonk
var_dump(debug_backtrace());

Est-ce que ça fait ce que tu veux?

7
inkedmn

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

6
Martin Geisler

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 
4
renenglish

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é.

3
Gumbo

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

2
augustowebd

debug_backtrace()

1
pix0r

Vous voudrez peut-être regarder dans debug_backtrace , ou peut-être debug_print_backtrace .

1
Rob

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

0
Geoff Kendall

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());
0
dev101