Uzyskaj nazwę funkcji dzwoniącego w PHP?


135

Czy istnieje funkcja PHP, aby znaleźć nazwę funkcji wywołującej w danej funkcji?


Powinieneś użyć Xdebug. Zobacz moją odpowiedź w tym poście: stackoverflow.com/questions/1513069/…
svassr

13
Xdebug to kategorycznie nie tylko funkcja PHP, która była pierwotnym żądaniem. Jeśli chcesz np. Użyć nazwy funkcji wywołującej w późniejszej logice PHP i nie instalować XDebug na serwerach produkcyjnych, potrzebujesz funkcji PHP.
JP,

Odpowiedzi:


198

Zobacz debug_backtrace - to może prześledzić twój stos wywołań aż do samego początku.

Oto, jak możesz zdobyć dzwoniącego:

$trace = debug_backtrace();
$caller = $trace[1];

echo "Called by {$caller['function']}";
if (isset($caller['class']))
    echo " in {$caller['class']}";

59
Wydaje mi się, że wypisuje to nazwę funkcji wywoływanej. Użyj, list(, $caller) = debug_backtrace(false);aby uzyskać dzwoniącego, falsedo wykonania ;-) (php5.3)
Znarkus

Wiele rozwiązań dostępnych w sieci pobiera drugi element tablicy śledzenia wstecznego, aby uzyskać wywołujący instancję: czy możemy być tego tak pewni? Czy zawsze szukamy drugiego elementu? Pomyślałem, że __construct (), który zawiera wewnątrz innego wywołania, takiego jak parent :: __ construct (), może przesunąć o inną pozycję prawdziwego wywołującego (jeszcze nie próbowałem).
Emanuele Del Grande,

1
Próbowałem sprawdzić kolejność wywołań zwracanych podczas korzystania z ReflectionClass i oczywiście zmienia to pozycję „prawdziwej” metody wywołującej, która jest widoczna w interfejsie użytkownika, więc nie można poczynić żadnych założeń dotyczących pozycji śledzenia wstecznego.
Emanuele Del Grande,

4
array shift usunie pierwszy element i zwróci usunięty element. Oryginalna tablica zostanie zmodyfikowana, co powinno dać wymagany wynikecho 'called by '.$trace[0]['function']
GoodSp33d

21
debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];aby uzyskać nazwę dzwoniącego z lepszą wydajnością.
ahuigo

17

Xdebug zapewnia kilka fajnych funkcji.

<?php
  Class MyClass
  {
    function __construct(){
        $this->callee();
    }
    function callee() {
        echo sprintf("callee() called @ %s: %s from %s::%s",
            xdebug_call_file(),
            xdebug_call_line(),
            xdebug_call_class(),
            xdebug_call_function()
        );
    }
  }
  $rollDebug = new MyClass();
?>

zwróci ślad

callee() called @ /var/www/xd.php: 16 from MyClass::__construct

Aby zainstalować Xdebug na Ubuntu, najlepszym sposobem jest

sudo aptitude install php5-xdebug

Być może będziesz musiał najpierw zainstalować php5-dev

sudo aptitude install php5-dev

więcej informacji


15

To bardzo późno, ale chciałbym udostępnić funkcję, która poda nazwę funkcji, z której jest wywoływana bieżąca funkcja.

public function getCallingFunctionName($completeTrace=false)
    {
        $trace=debug_backtrace();
        if($completeTrace)
        {
            $str = '';
            foreach($trace as $caller)
            {
                $str .= " -- Called by {$caller['function']}";
                if (isset($caller['class']))
                    $str .= " From Class {$caller['class']}";
            }
        }
        else
        {
            $caller=$trace[2];
            $str = "Called by {$caller['function']}";
            if (isset($caller['class']))
                $str .= " From Class {$caller['class']}";
        }
        return $str;
    }

Mam nadzieję, że to się przyda.


1
Nie ma za co, David !!! Używam tego również do debugowania w moim projekcie :)
MANISH ZOPE

Tryb „pełnego śledzenia” jest bardzo przydatny. Dzięki za udostępnienie.
Leopoldo Sanczyk


9
echo debug_backtrace()[1]['function'];

Działa od PHP 5.4 .

Lub zoptymalizowany (np. Dla przypadków użycia innych niż debugowanie):

echo debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];

Pierwszy argument zapobiega wypełnianiu nieużywanych argumentów funkcji, drugi ogranicza śledzenie do dwóch poziomów (potrzebujemy drugiego).


7

Zrobiłem to i używając tego sam

/**
 * Gets the caller of the function where this function is called from
 * @param string what to return? (Leave empty to get all, or specify: "class", "function", "line", "class", etc.) - options see: http://php.net/manual/en/function.debug-backtrace.php
 */
function getCaller($what = NULL)
{
    $trace = debug_backtrace();
    $previousCall = $trace[2]; // 0 is this call, 1 is call in previous function, 2 is caller of that function

    if(isset($what))
    {
        return $previousCall[$what];
    }
    else
    {
        return $previousCall;
    }   
}

3

Chciałem tylko powiedzieć, że sposób flori nie będzie działał jako funkcja, ponieważ zawsze zwróci nazwę wywoływanej funkcji zamiast wywołującego, ale nie mam reputacji komentowania. Stworzyłem bardzo prostą funkcję opartą na odpowiedzi flori, która działa dobrze w moim przypadku:

class basicFunctions{

    public function getCallerFunction(){
        return debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function'];
    }

}

PRZYKŁAD:

function a($authorisedFunctionsList = array("b")){
    $ref = new basicFunctions;
    $caller = $ref->getCallerFunction();

    if(in_array($caller,$authorisedFunctionsList)):
        echo "Welcome!";
        return true;
    else:
        echo "Unauthorised caller!";
        return false; 
    endif;
}

function b(){
    $executionContinues = $this->a();
    $executionContinues or exit;

    //Do something else..
}




1

To powinno działać:

$caller = next(debug_backtrace())['function'];

0

To ładnie to zrobi:


// Outputs an easy to read call trace
// Credit: https://www.php.net/manual/en/function.debug-backtrace.php#112238
// Gist: https://gist.github.com/UVLabs/692e542d3b53e079d36bc53b4ea20a4b

Class MyClass{

public function generateCallTrace()
{
    $e = new Exception();
    $trace = explode("\n", $e->getTraceAsString());
    // reverse array to make steps line up chronologically
    $trace = array_reverse($trace);
    array_shift($trace); // remove {main}
    array_pop($trace); // remove call to this method
    $length = count($trace);
    $result = array();
   
    for ($i = 0; $i < $length; $i++)
    {
        $result[] = ($i + 1)  . ')' . substr($trace[$i], strpos($trace[$i], ' ')); // replace '#someNum' with '$i)', set the right ordering
    }
   
    return "\t" . implode("\n\t", $result);
}

}

// call function where needed to output call trace

/**
Example output:
1) /var/www/test/test.php(15): SomeClass->__construct()
2) /var/www/test/SomeClass.class.php(36): SomeClass->callSomething()
**/```
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.