2017-12-31 146 views
6

Ich möchte register_tick_function() verwenden, um die folgenden Aufrufe haken und drucken ihre Stack-Trace mit debug_backtrace().PHP debug_backtrace() von register_tick_function() aufgerufen wird nicht den vollständigen Stapel

Wenn ich den folgenden Code ausführen.

<?php 

function dump() { 
    // Replace this with var_dump(debug_backtrace()); to print the entire trace. 
    foreach (debug_backtrace() as $trace) 
    echo("Function ${trace['function']}() has been called" . PHP_EOL); 
} 

declare(ticks = 1); 
register_tick_function('dump'); 

print(""); 
array_search('green', Array()); 

Es druckt nur die dump() Funktion.

Function dump() has been called 
Function dump() has been called 
Function dump() has been called 

Warum ich sehe nicht print() und array_search() Trace-Daten? Es ist so, als ob der Stapel vor dem Aufruf von dump() zurückgesetzt wurde. Ich bin mir auch ziemlich sicher, dass es in der Vergangenheit richtig funktioniert hat.

+2

Dies als Fehler vor ein paar Jahren berichtet wurde, war aber dann nicht reproduzierbar: https://bugs.php.net/bug.php? id = 70188 –

+0

Getestet. Kann in PHP 7.1 auf Win, Ubuntu, Docker (Ubuntu) nicht replizieren. Kann nicht in PHP 5.6 auf Win, Ubuntu, Docker (Ubuntu) replizieren. –

+1

Ich habe das auf http://phpio.net/s/6v6g versucht, und es scheint auch in keiner der PHP-Versionen dort zu funktionieren. So sehen Sie dieses: https://stackoverflow.com/questions/7241834/debug-backtrace-from-registered-shutdown-function-in-php. Obwohl es sich um register_shutdown_function handelt, kann es dasselbe sein. Die Ablaufverfolgung kann nur von der Stelle aus beginnen, an der sie aufgerufen wird, was in diesem Fall möglicherweise nicht der Fall ist. Es ist mehr wie folgt: 'print (" ");' 'dump();' 'array_search ('grün', Array());' 'dump();' Also in diesem Fall, es verfolgt sich selbst, da es von innen nichts anderes genannt wird. – Huy

Antwort

1

Sie missverstehen, was der Backtrace ist, dieser Stapel ist keine Liste von Funktionen, die PHP vor Erreichen einer bestimmten Codezeile ausführt, sondern die Liste verschachtelter Funktionen, die den PHP-Interpreter für eine bestimmte Codezeile rechtfertigen .

Das erste Element wird immer die Funktion sein, in der Sie sich gerade befinden, die nächste ist die Funktion, die diese Funktion aufgerufen hat und so weiter. Wenn eine Funktion zurückkehrt, befindet sie sich nicht mehr im Stapel.

class Foo { 
    public static function bar() { 
     return self::say(); 
    } 

    public static function say() { 
     return debug_backtrace(); 
    } 
} 

var_dump(Foo::say()); 
//[0] => say() 

var_dump(Foo::bar()); 
//[0] => say(); 
//[1] => bar(); 

//Note that this behaviour work the same for require(), include() and eval() 

require_once('test.php'); 

//test.php: 
var_dump(debug_backtrace()); 
//[0] => require_once() 

Während PHP Ihr Skript interpretiert, navigiert es Ihre Funktionen, Hinzufügen und Entfernen aus dem aktuellen Stapel. Der Stack des Backtrace ist nicht der Ort, an dem PHP protokolliert, welche Funktionen in chronologischer Reihenfolge aufgerufen wurden.

Für letztere ist dies eine Lösung, die ich gefunden: Get a called functions list in PHP