PHP: Bestimmen Sie, woher die Funktion aufgerufen wurde

93

Gibt es eine Möglichkeit herauszufinden, woher eine Funktion in PHP aufgerufen wurde? Beispiel:

function epic()
{
  fail();
}

function fail()
{
  //at this point, how do i know, that epic() has called this function?
}
pol_b
quelle

Antworten:

128

Sie können verwenden debug_backtrace().

Beispiel:

<?php

function epic( $a, $b )
{
    fail( $a . ' ' . $b );
}

function fail( $string )
{
    $backtrace = debug_backtrace();

    print_r( $backtrace );
}

epic( 'Hello', 'World' );

Ausgabe:

Array
(
    [0] => Array
        (
            [file] => /Users/romac/Desktop/test.php
            [line] => 5
            [function] => fail
            [args] => Array
                (
                    [0] => Hello World
                )

        )

    [1] => Array
        (
            [file] => /Users/romac/Desktop/test.php
            [line] => 15
            [function] => epic
            [args] => Array
                (
                    [0] => Hello
                    [1] => World
                )

        )

)
Romac
quelle
5
Zum ersten Mal fand ich, debug_backtrace()was für eine hervorragende Funktion. Ich werde diesen verwenden!
David Yell
26

Verwendung debug_backtrace():

function fail()
{
    $backtrace = debug_backtrace();

    // Here, $backtrace[0] points to fail(), so we'll look in $backtrace[1] instead
    if (isset($backtrace[1]['function']) && $backtrace[1]['function'] == 'epic')
    {
        // Called by epic()...
    }
}
BoltClock
quelle
9
Das macht definitiv was du willst. Aber Vorsicht debug_backtrace()ist ein teurer Anruf. Gewöhnen Sie sich nicht an, damit Anrufketten zu bestimmen. Wenn Sie diese Funktionen "schützen" möchten, lesen Sie OOP und geschützte Methoden.
Ircmaxell
18

Schnellste und einfachste Lösung, wie ich gefunden habe

public function func() { //function whose call file you want to find
    $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
}

$trace: Array
(
    [0] => Array
        (
            [file] => C:\wamp\www\index.php
            [line] => 56
            [function] => func
            [class] => (func Class namespace)
            [type] => ->
        )

)

Ich teste die Geschwindigkeit auf einem Lenovo Laptop: Intel Pentiom CPU N3530 2.16GHz, RAM 8GB

global $times;
$start = microtime(true);
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
$times[] = microtime(true) - $start;

Ergebnisse:

count($times):  97
min:    2.6941299438477E-5
max:   10.68115234375E-5
avg:    3.3095939872191E-5
median: 3.0517578125E-5
sum:  321.03061676025E-5

the same results with notation without E-5
count($times):  97
min:    0.000026941299438477
max:    0.0001068115234375
avg:    0.000033095939872191
median: 0.000030517578125
sum:    0.0032103061676025
Mariusz Charczuk
quelle
Für mich war DEBUG_BACKTRACE_IGNORE_ARGS sehr nützlich, ohne es gab es viel zu viele Informationen.
Arie
15

Wenn Sie also immer noch WIRKLICH nicht wissen wie, dann ist hier die Lösung:

$backtrace = debug_backtrace();
echo 'Mu name is '.$backtrace[1]['function'].', and I have called him! Muahahah!';
Marverix
quelle
1
Sie könnten also verwenden, wenn ($ backtrace [1] ['function'] == 'epic') {// einige Sachen machen; sonst mach noch ein paar andere Sachen; } ?? wow
Buttle Butkus
2
Ja, aber nicht! Jedenfalls nicht im permanenten Anwendungscode. Verwenden Sie Parameter. debug_backtrace () sieht nach einer ziemlich schweren Operation aus.
Kluny
3

Versuchen Sie es mit dem folgenden Code.

foreach(debug_backtrace() as $t) {              
   echo $t['file'] . ' line ' . $t['line'] . ' calls ' . $t['function'] . "()<br/>";
}
Makwana Ketan
quelle
Gute und direkte Lösung, um alle Dateien zurückzuverfolgen, von denen eine bestimmte Funktion aufgerufen wird.
Ausnahme
3

Wenn Sie den genauen Ursprung des Aufrufs oben im Stapel verfolgen möchten, können Sie den folgenden Code verwenden:

$call_origin = end(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));

Dadurch werden verkettete Funktionen ignoriert und nur die relevantesten Anrufinformationen abgerufen (relevant wird lose verwendet, da dies davon abhängt, was Sie erreichen möchten).

Phillip Weber
quelle
Danke dir. das hat mir viel zeit gespart :)
Mohamed hesham
-1
function findFunction($function, $inputDirectory=""){
    //version 0.1
    $docRoot = getenv("DOCUMENT_ROOT");
    $folderArray = null;
    $dirArray = null;

    // open directory
    $directory = opendir($docRoot.$inputDirectory);

    // get each entry
    while($entryName = readdir($directory)) {
        if(is_dir($entryName) && $entryName != "." && $entryName != ".."){
            $folderArray[] = str_replace($inputDirectory, "", $entryName);
        }
        $ext = explode(".", $entryName);
        if(!empty($ext[1])){
            $dirArray[] = $docRoot.$inputDirectory."/".$entryName;
        }
    }

    // close directory
    closedir($directory);
    $found = false;

    if(is_array($dirArray)){
        foreach($dirArray as $current){
            $myFile = file_get_contents($current);
            $myFile = str_replace("<?php", "", $myFile);
            $myFile = str_replace("?>", "", $myFile);
            if(preg_match("/function ".$function."/", $myFile)){
                $found = true;
                $foundLocation = $current;
                break;
            }
        }
    }
    if($found){
        echo $foundLocation;
        exit;
    } else if(is_array($folderArray)){
        foreach($folderArray as $folder){
            if(!isset($return)){
                $return = findFunction($function, $inputDirectory."/".$folder);
            } else if($return == false){
                $return = findFunction($function, $inputDirectory."/".$folder);
            }
        }
    } else {
        return false;
    }
}

findFunction("testFunction", "rootDirectory");

Hoffe es hilft jemandem. Wenn sich die eigentliche Funktion außerhalb von httpdocs befindet, kann sie nicht gefunden werden, da der Server so eingerichtet wird, dass sie dies nicht zulässt. Es wurde nur einen Ordner tief getestet, aber die rekursive Methodik sollte theoretisch funktionieren.

Dies ist wie Version 0.1, aber ich beabsichtige nicht, sie weiterzuentwickeln. Wenn jemand sie aktualisiert, können Sie sie gerne erneut veröffentlichen.

Außerirdischer
quelle
Zu viel Arbeit: Fügen Sie dies zu .bashrc hinzu function ff() { grep "function $1" $(find ./ -name "*.php") } und rufen Sie dann ff failoder auf ff epic. siehe: github.com/MaerF0x0/VimSetup/blob/master/bashrc#L122
Mike Graf