php: определить, откуда была вызвана функция - PullRequest
90 голосов
/ 02 июня 2010

есть ли способ узнать, откуда была вызвана функция в PHP? Пример:

function epic()
{
  fail();
}

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

Ответы [ 8 ]

122 голосов
/ 02 июня 2010

Вы можете использовать debug_backtrace().

Пример:

<?php

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

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

    print_r( $backtrace );
}

epic( 'Hello', 'World' );

Выход:

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
                )

        )

)
24 голосов
/ 02 июня 2010

Использование 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()...
    }
}
16 голосов
/ 16 сентября 2016

Самое быстрое и простое решение, как я нашел

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

)

Я тестирую скорость на ноутбуке Lenovo: процессор Intel Pentiom N3530 2,16 ГГц, оперативная память 8 ГБ

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

Результаты:

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
14 голосов
/ 21 июня 2012

Так что, если вы ДЕЙСТВИТЕЛЬНО не знаете как, то вот решение:

$backtrace = debug_backtrace();
echo 'Mu name is '.$backtrace[1]['function'].', and I have called him! Muahahah!';
5 голосов
/ 02 июня 2010

Используйте функцию debug_backtrace: http://php.net/manual/en/function.debug-backtrace.php

3 голосов
/ 28 декабря 2017

Если вы хотите отследить точное происхождение вызова на вершине стека, вы можете использовать следующий код:

$call_origin = end(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));

Это будет игнорировать связанные функции и получать только наиболее релевантную информацию о вызовах (релевантно используется свободно, поскольку это зависит от того, что вы пытаетесь выполнить).

3 голосов
/ 28 апреля 2016

Попробуйте код ниже.

foreach(debug_backtrace() as $t) {              
   echo $t['file'] . ' line ' . $t['line'] . ' calls ' . $t['function'] . "()<br/>";
}
0 голосов
/ 08 ноября 2011
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");

Надеюсь, это кому-нибудь поможет.Если фактическая функция находится за пределами httpdocs, ее нельзя найти, поскольку сервер будет настроен так, чтобы запретить это.Только проверил это на глубину одной папки, но рекурсивная методология должна работать теоретически.

Это похоже на версию 0.1, но я не собираюсь продолжать разработку, поэтому, если кто-то обновит, не стесняйтесь перепечатывать ее.

...