Pregunta

Estoy buscando una manera de imprimir la pila de llamadas en PHP.

Puntos de bonificación si la función vacía el búfer IO.

¿Fue útil?

Solución

Si desea generar una traza inversa, está buscando < code> debug_backtrace y / o debug_print_backtrace .


El primero, por ejemplo, le dará una matriz como esta (citando el manual) :

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


Aparentemente, no vaciarán el búfer de E / S, pero puede hacerlo usted mismo, con flush y / o ob_flush .

(consulte la página del manual de la primera para averiguar por qué " y / o " ;))

Otros consejos

Más legible 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}"

Para registrar el seguimiento

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

Gracias @Tobiasz

Backtrace arroja una gran cantidad de basura que no necesita. Se tarda mucho, es difícil de leer. Todo lo que siempre quieres es "¿qué se llama qué de dónde?" Aquí hay una solución simple de función estática. Por lo general, lo pongo en una clase llamada 'depuración', que contiene todas mis funciones de utilidad de depuración.

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 llamas así:

debugUtils::callStack(debug_backtrace());

Y produce resultados como este:

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

Es extraño que nadie haya publicado de esta manera:

debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);

En realidad, esto imprime la traza inversa sin la basura, solo qué método se llamó y dónde.

Si desea un seguimiento de la pila que se parezca mucho a cómo php formatea el seguimiento de la pila de excepción que usar esta función, escribí:

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

Esto devolverá un seguimiento de pila formateado así:

#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());

¿Eso hace lo que quieres?

Ver debug_print_backtrace . Supongo que puede llamar a flush después si lo desea.

phptrace es una gran herramienta para imprimir la pila PHP en cualquier momento cuando lo desee sin instalar ninguna extensión.

Hay dos funciones principales de phptrace: primero, imprimir la pila de llamadas de PHP que no necesita instalar nada, segundo, rastrear los flujos de ejecución de php que necesitan instalar la extensión que proporciona.

como sigue:

$ ./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 

Utilice debug_backtrace para obtener un seguimiento de las funciones y métodos que tenían se llamó y qué archivos se incluyeron que llevaron al punto donde se ha llamado a debug_backtrace .

por favor, eche un vistazo a esta clase de utilidades, puede ser útil:

Uso:

<?php
/* first caller */
 Who::callme();

/* list the entire list of calls */
Who::followme();

Clase de origen: https://github.com/augustowebd/utils/blob /master/Who.php

debug_backtrace()

Es posible que desee consultar debug_backtrace , o tal vez debug_print_backtrace .

La solución de Walltearer es excelente, particularmente si está encerrada en una etiqueta 'pre':

<pre>
<?php debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); ?>
</pre>

- que establece las llamadas en líneas separadas, perfectamente numeradas

He adaptado la respuesta de Don Briggs anterior para utilizar el registro de errores internos en lugar de la impresión pública, lo que puede ser su gran preocupación cuando se trabaja en un servidor en vivo. Además, se agregaron algunas modificaciones más, como la opción de incluir la ruta completa del archivo en lugar del nombre básico (porque podría haber archivos con el mismo nombre en diferentes rutas) y también (para aquellos que lo requieran) una salida completa de la pila de nodos:

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());
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top